Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ bdf9f35d

History | View | Annotate | Download (94.4 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
typedef struct CCTable {
864
    uint32_t (*compute_all)(void); /* return all the flags */
865
    uint32_t (*compute_c)(void);  /* return the C flag */
866
} CCTable;
867

    
868
static const CCTable icc_table[CC_OP_NB] = {
869
    /* CC_OP_DYNAMIC should never happen */
870
    [CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
871
    [CC_OP_ADD] = { compute_all_add, compute_C_add },
872
};
873

    
874
#ifdef TARGET_SPARC64
875
static const CCTable xcc_table[CC_OP_NB] = {
876
    /* CC_OP_DYNAMIC should never happen */
877
    [CC_OP_FLAGS] = { compute_all_flags_xcc, compute_C_flags_xcc },
878
    [CC_OP_ADD] = { compute_all_add_xcc, compute_C_add_xcc },
879
};
880
#endif
881

    
882
void helper_compute_psr(void)
883
{
884
    uint32_t new_psr;
885

    
886
    new_psr = icc_table[CC_OP].compute_all();
887
    env->psr = new_psr;
888
#ifdef TARGET_SPARC64
889
    new_psr = xcc_table[CC_OP].compute_all();
890
    env->xcc = new_psr;
891
#endif
892
    CC_OP = CC_OP_FLAGS;
893
}
894

    
895
uint32_t helper_compute_C_icc(void)
896
{
897
    uint32_t ret;
898

    
899
    ret = icc_table[CC_OP].compute_c() >> PSR_CARRY_SHIFT;
900
    return ret;
901
}
902

    
903
#ifdef TARGET_SPARC64
904
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
905
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
906
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
907

    
908
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
909
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
910
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
911

    
912
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
913
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
914
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
915

    
916
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
917
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
918
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
919

    
920
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
921
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
922
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
923

    
924
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
925
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
926
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
927
#endif
928
#undef GEN_FCMPS
929

    
930
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
931
    defined(DEBUG_MXCC)
932
static void dump_mxcc(CPUState *env)
933
{
934
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
935
           env->mxccdata[0], env->mxccdata[1],
936
           env->mxccdata[2], env->mxccdata[3]);
937
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
938
           "          %016llx %016llx %016llx %016llx\n",
939
           env->mxccregs[0], env->mxccregs[1],
940
           env->mxccregs[2], env->mxccregs[3],
941
           env->mxccregs[4], env->mxccregs[5],
942
           env->mxccregs[6], env->mxccregs[7]);
943
}
944
#endif
945

    
946
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
947
    && defined(DEBUG_ASI)
948
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
949
                     uint64_t r1)
950
{
951
    switch (size)
952
    {
953
    case 1:
954
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
955
                    addr, asi, r1 & 0xff);
956
        break;
957
    case 2:
958
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
959
                    addr, asi, r1 & 0xffff);
960
        break;
961
    case 4:
962
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
963
                    addr, asi, r1 & 0xffffffff);
964
        break;
965
    case 8:
966
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
967
                    addr, asi, r1);
968
        break;
969
    }
970
}
971
#endif
972

    
973
#ifndef TARGET_SPARC64
974
#ifndef CONFIG_USER_ONLY
975
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
976
{
977
    uint64_t ret = 0;
978
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
979
    uint32_t last_addr = addr;
980
#endif
981

    
982
    helper_check_align(addr, size - 1);
983
    switch (asi) {
984
    case 2: /* SuperSparc MXCC registers */
985
        switch (addr) {
986
        case 0x01c00a00: /* MXCC control register */
987
            if (size == 8)
988
                ret = env->mxccregs[3];
989
            else
990
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
991
                             size);
992
            break;
993
        case 0x01c00a04: /* MXCC control register */
994
            if (size == 4)
995
                ret = env->mxccregs[3];
996
            else
997
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
998
                             size);
999
            break;
1000
        case 0x01c00c00: /* Module reset register */
1001
            if (size == 8) {
1002
                ret = env->mxccregs[5];
1003
                // should we do something here?
1004
            } else
1005
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1006
                             size);
1007
            break;
1008
        case 0x01c00f00: /* MBus port address register */
1009
            if (size == 8)
1010
                ret = env->mxccregs[7];
1011
            else
1012
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1013
                             size);
1014
            break;
1015
        default:
1016
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1017
                         size);
1018
            break;
1019
        }
1020
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
1021
                     "addr = %08x -> ret = %" PRIx64 ","
1022
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1023
#ifdef DEBUG_MXCC
1024
        dump_mxcc(env);
1025
#endif
1026
        break;
1027
    case 3: /* MMU probe */
1028
        {
1029
            int mmulev;
1030

    
1031
            mmulev = (addr >> 8) & 15;
1032
            if (mmulev > 4)
1033
                ret = 0;
1034
            else
1035
                ret = mmu_probe(env, addr, mmulev);
1036
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
1037
                        addr, mmulev, ret);
1038
        }
1039
        break;
1040
    case 4: /* read MMU regs */
1041
        {
1042
            int reg = (addr >> 8) & 0x1f;
1043

    
1044
            ret = env->mmuregs[reg];
1045
            if (reg == 3) /* Fault status cleared on read */
1046
                env->mmuregs[3] = 0;
1047
            else if (reg == 0x13) /* Fault status read */
1048
                ret = env->mmuregs[3];
1049
            else if (reg == 0x14) /* Fault address read */
1050
                ret = env->mmuregs[4];
1051
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1052
        }
1053
        break;
1054
    case 5: // Turbosparc ITLB Diagnostic
1055
    case 6: // Turbosparc DTLB Diagnostic
1056
    case 7: // Turbosparc IOTLB Diagnostic
1057
        break;
1058
    case 9: /* Supervisor code access */
1059
        switch(size) {
1060
        case 1:
1061
            ret = ldub_code(addr);
1062
            break;
1063
        case 2:
1064
            ret = lduw_code(addr);
1065
            break;
1066
        default:
1067
        case 4:
1068
            ret = ldl_code(addr);
1069
            break;
1070
        case 8:
1071
            ret = ldq_code(addr);
1072
            break;
1073
        }
1074
        break;
1075
    case 0xa: /* User data access */
1076
        switch(size) {
1077
        case 1:
1078
            ret = ldub_user(addr);
1079
            break;
1080
        case 2:
1081
            ret = lduw_user(addr);
1082
            break;
1083
        default:
1084
        case 4:
1085
            ret = ldl_user(addr);
1086
            break;
1087
        case 8:
1088
            ret = ldq_user(addr);
1089
            break;
1090
        }
1091
        break;
1092
    case 0xb: /* Supervisor data access */
1093
        switch(size) {
1094
        case 1:
1095
            ret = ldub_kernel(addr);
1096
            break;
1097
        case 2:
1098
            ret = lduw_kernel(addr);
1099
            break;
1100
        default:
1101
        case 4:
1102
            ret = ldl_kernel(addr);
1103
            break;
1104
        case 8:
1105
            ret = ldq_kernel(addr);
1106
            break;
1107
        }
1108
        break;
1109
    case 0xc: /* I-cache tag */
1110
    case 0xd: /* I-cache data */
1111
    case 0xe: /* D-cache tag */
1112
    case 0xf: /* D-cache data */
1113
        break;
1114
    case 0x20: /* MMU passthrough */
1115
        switch(size) {
1116
        case 1:
1117
            ret = ldub_phys(addr);
1118
            break;
1119
        case 2:
1120
            ret = lduw_phys(addr);
1121
            break;
1122
        default:
1123
        case 4:
1124
            ret = ldl_phys(addr);
1125
            break;
1126
        case 8:
1127
            ret = ldq_phys(addr);
1128
            break;
1129
        }
1130
        break;
1131
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1132
        switch(size) {
1133
        case 1:
1134
            ret = ldub_phys((target_phys_addr_t)addr
1135
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1136
            break;
1137
        case 2:
1138
            ret = lduw_phys((target_phys_addr_t)addr
1139
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
1140
            break;
1141
        default:
1142
        case 4:
1143
            ret = ldl_phys((target_phys_addr_t)addr
1144
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1145
            break;
1146
        case 8:
1147
            ret = ldq_phys((target_phys_addr_t)addr
1148
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
1149
            break;
1150
        }
1151
        break;
1152
    case 0x30: // Turbosparc secondary cache diagnostic
1153
    case 0x31: // Turbosparc RAM snoop
1154
    case 0x32: // Turbosparc page table descriptor diagnostic
1155
    case 0x39: /* data cache diagnostic register */
1156
        ret = 0;
1157
        break;
1158
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
1159
        {
1160
            int reg = (addr >> 8) & 3;
1161

    
1162
            switch(reg) {
1163
            case 0: /* Breakpoint Value (Addr) */
1164
                ret = env->mmubpregs[reg];
1165
                break;
1166
            case 1: /* Breakpoint Mask */
1167
                ret = env->mmubpregs[reg];
1168
                break;
1169
            case 2: /* Breakpoint Control */
1170
                ret = env->mmubpregs[reg];
1171
                break;
1172
            case 3: /* Breakpoint Status */
1173
                ret = env->mmubpregs[reg];
1174
                env->mmubpregs[reg] = 0ULL;
1175
                break;
1176
            }
1177
            DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
1178
        }
1179
        break;
1180
    case 8: /* User code access, XXX */
1181
    default:
1182
        do_unassigned_access(addr, 0, 0, asi, size);
1183
        ret = 0;
1184
        break;
1185
    }
1186
    if (sign) {
1187
        switch(size) {
1188
        case 1:
1189
            ret = (int8_t) ret;
1190
            break;
1191
        case 2:
1192
            ret = (int16_t) ret;
1193
            break;
1194
        case 4:
1195
            ret = (int32_t) ret;
1196
            break;
1197
        default:
1198
            break;
1199
        }
1200
    }
1201
#ifdef DEBUG_ASI
1202
    dump_asi("read ", last_addr, asi, size, ret);
1203
#endif
1204
    return ret;
1205
}
1206

    
1207
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1208
{
1209
    helper_check_align(addr, size - 1);
1210
    switch(asi) {
1211
    case 2: /* SuperSparc MXCC registers */
1212
        switch (addr) {
1213
        case 0x01c00000: /* MXCC stream data register 0 */
1214
            if (size == 8)
1215
                env->mxccdata[0] = val;
1216
            else
1217
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1218
                             size);
1219
            break;
1220
        case 0x01c00008: /* MXCC stream data register 1 */
1221
            if (size == 8)
1222
                env->mxccdata[1] = val;
1223
            else
1224
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1225
                             size);
1226
            break;
1227
        case 0x01c00010: /* MXCC stream data register 2 */
1228
            if (size == 8)
1229
                env->mxccdata[2] = val;
1230
            else
1231
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1232
                             size);
1233
            break;
1234
        case 0x01c00018: /* MXCC stream data register 3 */
1235
            if (size == 8)
1236
                env->mxccdata[3] = val;
1237
            else
1238
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1239
                             size);
1240
            break;
1241
        case 0x01c00100: /* MXCC stream source */
1242
            if (size == 8)
1243
                env->mxccregs[0] = val;
1244
            else
1245
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1246
                             size);
1247
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1248
                                        0);
1249
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1250
                                        8);
1251
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1252
                                        16);
1253
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
1254
                                        24);
1255
            break;
1256
        case 0x01c00200: /* MXCC stream destination */
1257
            if (size == 8)
1258
                env->mxccregs[1] = val;
1259
            else
1260
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1261
                             size);
1262
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
1263
                     env->mxccdata[0]);
1264
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
1265
                     env->mxccdata[1]);
1266
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
1267
                     env->mxccdata[2]);
1268
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
1269
                     env->mxccdata[3]);
1270
            break;
1271
        case 0x01c00a00: /* MXCC control register */
1272
            if (size == 8)
1273
                env->mxccregs[3] = val;
1274
            else
1275
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1276
                             size);
1277
            break;
1278
        case 0x01c00a04: /* MXCC control register */
1279
            if (size == 4)
1280
                env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
1281
                    | val;
1282
            else
1283
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1284
                             size);
1285
            break;
1286
        case 0x01c00e00: /* MXCC error register  */
1287
            // writing a 1 bit clears the error
1288
            if (size == 8)
1289
                env->mxccregs[6] &= ~val;
1290
            else
1291
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1292
                             size);
1293
            break;
1294
        case 0x01c00f00: /* MBus port address register */
1295
            if (size == 8)
1296
                env->mxccregs[7] = val;
1297
            else
1298
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
1299
                             size);
1300
            break;
1301
        default:
1302
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
1303
                         size);
1304
            break;
1305
        }
1306
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
1307
                     asi, size, addr, val);
1308
#ifdef DEBUG_MXCC
1309
        dump_mxcc(env);
1310
#endif
1311
        break;
1312
    case 3: /* MMU flush */
1313
        {
1314
            int mmulev;
1315

    
1316
            mmulev = (addr >> 8) & 15;
1317
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1318
            switch (mmulev) {
1319
            case 0: // flush page
1320
                tlb_flush_page(env, addr & 0xfffff000);
1321
                break;
1322
            case 1: // flush segment (256k)
1323
            case 2: // flush region (16M)
1324
            case 3: // flush context (4G)
1325
            case 4: // flush entire
1326
                tlb_flush(env, 1);
1327
                break;
1328
            default:
1329
                break;
1330
            }
1331
#ifdef DEBUG_MMU
1332
            dump_mmu(env);
1333
#endif
1334
        }
1335
        break;
1336
    case 4: /* write MMU regs */
1337
        {
1338
            int reg = (addr >> 8) & 0x1f;
1339
            uint32_t oldreg;
1340

    
1341
            oldreg = env->mmuregs[reg];
1342
            switch(reg) {
1343
            case 0: // Control Register
1344
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1345
                                    (val & 0x00ffffff);
1346
                // Mappings generated during no-fault mode or MMU
1347
                // disabled mode are invalid in normal mode
1348
                if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
1349
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1350
                    tlb_flush(env, 1);
1351
                break;
1352
            case 1: // Context Table Pointer Register
1353
                env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
1354
                break;
1355
            case 2: // Context Register
1356
                env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1357
                if (oldreg != env->mmuregs[reg]) {
1358
                    /* we flush when the MMU context changes because
1359
                       QEMU has no MMU context support */
1360
                    tlb_flush(env, 1);
1361
                }
1362
                break;
1363
            case 3: // Synchronous Fault Status Register with Clear
1364
            case 4: // Synchronous Fault Address Register
1365
                break;
1366
            case 0x10: // TLB Replacement Control Register
1367
                env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1368
                break;
1369
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1370
                env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
1371
                break;
1372
            case 0x14: // Synchronous Fault Address Register
1373
                env->mmuregs[4] = val;
1374
                break;
1375
            default:
1376
                env->mmuregs[reg] = val;
1377
                break;
1378
            }
1379
            if (oldreg != env->mmuregs[reg]) {
1380
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
1381
                            reg, oldreg, env->mmuregs[reg]);
1382
            }
1383
#ifdef DEBUG_MMU
1384
            dump_mmu(env);
1385
#endif
1386
        }
1387
        break;
1388
    case 5: // Turbosparc ITLB Diagnostic
1389
    case 6: // Turbosparc DTLB Diagnostic
1390
    case 7: // Turbosparc IOTLB Diagnostic
1391
        break;
1392
    case 0xa: /* User data access */
1393
        switch(size) {
1394
        case 1:
1395
            stb_user(addr, val);
1396
            break;
1397
        case 2:
1398
            stw_user(addr, val);
1399
            break;
1400
        default:
1401
        case 4:
1402
            stl_user(addr, val);
1403
            break;
1404
        case 8:
1405
            stq_user(addr, val);
1406
            break;
1407
        }
1408
        break;
1409
    case 0xb: /* Supervisor data access */
1410
        switch(size) {
1411
        case 1:
1412
            stb_kernel(addr, val);
1413
            break;
1414
        case 2:
1415
            stw_kernel(addr, val);
1416
            break;
1417
        default:
1418
        case 4:
1419
            stl_kernel(addr, val);
1420
            break;
1421
        case 8:
1422
            stq_kernel(addr, val);
1423
            break;
1424
        }
1425
        break;
1426
    case 0xc: /* I-cache tag */
1427
    case 0xd: /* I-cache data */
1428
    case 0xe: /* D-cache tag */
1429
    case 0xf: /* D-cache data */
1430
    case 0x10: /* I/D-cache flush page */
1431
    case 0x11: /* I/D-cache flush segment */
1432
    case 0x12: /* I/D-cache flush region */
1433
    case 0x13: /* I/D-cache flush context */
1434
    case 0x14: /* I/D-cache flush user */
1435
        break;
1436
    case 0x17: /* Block copy, sta access */
1437
        {
1438
            // val = src
1439
            // addr = dst
1440
            // copy 32 bytes
1441
            unsigned int i;
1442
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1443

    
1444
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1445
                temp = ldl_kernel(src);
1446
                stl_kernel(dst, temp);
1447
            }
1448
        }
1449
        break;
1450
    case 0x1f: /* Block fill, stda access */
1451
        {
1452
            // addr = dst
1453
            // fill 32 bytes with val
1454
            unsigned int i;
1455
            uint32_t dst = addr & 7;
1456

    
1457
            for (i = 0; i < 32; i += 8, dst += 8)
1458
                stq_kernel(dst, val);
1459
        }
1460
        break;
1461
    case 0x20: /* MMU passthrough */
1462
        {
1463
            switch(size) {
1464
            case 1:
1465
                stb_phys(addr, val);
1466
                break;
1467
            case 2:
1468
                stw_phys(addr, val);
1469
                break;
1470
            case 4:
1471
            default:
1472
                stl_phys(addr, val);
1473
                break;
1474
            case 8:
1475
                stq_phys(addr, val);
1476
                break;
1477
            }
1478
        }
1479
        break;
1480
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1481
        {
1482
            switch(size) {
1483
            case 1:
1484
                stb_phys((target_phys_addr_t)addr
1485
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1486
                break;
1487
            case 2:
1488
                stw_phys((target_phys_addr_t)addr
1489
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1490
                break;
1491
            case 4:
1492
            default:
1493
                stl_phys((target_phys_addr_t)addr
1494
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1495
                break;
1496
            case 8:
1497
                stq_phys((target_phys_addr_t)addr
1498
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1499
                break;
1500
            }
1501
        }
1502
        break;
1503
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1504
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1505
               // Turbosparc snoop RAM
1506
    case 0x32: // store buffer control or Turbosparc page table
1507
               // descriptor diagnostic
1508
    case 0x36: /* I-cache flash clear */
1509
    case 0x37: /* D-cache flash clear */
1510
    case 0x4c: /* breakpoint action */
1511
        break;
1512
    case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
1513
        {
1514
            int reg = (addr >> 8) & 3;
1515

    
1516
            switch(reg) {
1517
            case 0: /* Breakpoint Value (Addr) */
1518
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1519
                break;
1520
            case 1: /* Breakpoint Mask */
1521
                env->mmubpregs[reg] = (val & 0xfffffffffULL);
1522
                break;
1523
            case 2: /* Breakpoint Control */
1524
                env->mmubpregs[reg] = (val & 0x7fULL);
1525
                break;
1526
            case 3: /* Breakpoint Status */
1527
                env->mmubpregs[reg] = (val & 0xfULL);
1528
                break;
1529
            }
1530
            DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
1531
                        env->mmuregs[reg]);
1532
        }
1533
        break;
1534
    case 8: /* User code access, XXX */
1535
    case 9: /* Supervisor code access, XXX */
1536
    default:
1537
        do_unassigned_access(addr, 1, 0, asi, size);
1538
        break;
1539
    }
1540
#ifdef DEBUG_ASI
1541
    dump_asi("write", addr, asi, size, val);
1542
#endif
1543
}
1544

    
1545
#endif /* CONFIG_USER_ONLY */
1546
#else /* TARGET_SPARC64 */
1547

    
1548
#ifdef CONFIG_USER_ONLY
1549
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1550
{
1551
    uint64_t ret = 0;
1552
#if defined(DEBUG_ASI)
1553
    target_ulong last_addr = addr;
1554
#endif
1555

    
1556
    if (asi < 0x80)
1557
        raise_exception(TT_PRIV_ACT);
1558

    
1559
    helper_check_align(addr, size - 1);
1560
    address_mask(env, &addr);
1561

    
1562
    switch (asi) {
1563
    case 0x82: // Primary no-fault
1564
    case 0x8a: // Primary no-fault LE
1565
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1566
#ifdef DEBUG_ASI
1567
            dump_asi("read ", last_addr, asi, size, ret);
1568
#endif
1569
            return 0;
1570
        }
1571
        // Fall through
1572
    case 0x80: // Primary
1573
    case 0x88: // Primary LE
1574
        {
1575
            switch(size) {
1576
            case 1:
1577
                ret = ldub_raw(addr);
1578
                break;
1579
            case 2:
1580
                ret = lduw_raw(addr);
1581
                break;
1582
            case 4:
1583
                ret = ldl_raw(addr);
1584
                break;
1585
            default:
1586
            case 8:
1587
                ret = ldq_raw(addr);
1588
                break;
1589
            }
1590
        }
1591
        break;
1592
    case 0x83: // Secondary no-fault
1593
    case 0x8b: // Secondary no-fault LE
1594
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1595
#ifdef DEBUG_ASI
1596
            dump_asi("read ", last_addr, asi, size, ret);
1597
#endif
1598
            return 0;
1599
        }
1600
        // Fall through
1601
    case 0x81: // Secondary
1602
    case 0x89: // Secondary LE
1603
        // XXX
1604
        break;
1605
    default:
1606
        break;
1607
    }
1608

    
1609
    /* Convert from little endian */
1610
    switch (asi) {
1611
    case 0x88: // Primary LE
1612
    case 0x89: // Secondary LE
1613
    case 0x8a: // Primary no-fault LE
1614
    case 0x8b: // Secondary no-fault LE
1615
        switch(size) {
1616
        case 2:
1617
            ret = bswap16(ret);
1618
            break;
1619
        case 4:
1620
            ret = bswap32(ret);
1621
            break;
1622
        case 8:
1623
            ret = bswap64(ret);
1624
            break;
1625
        default:
1626
            break;
1627
        }
1628
    default:
1629
        break;
1630
    }
1631

    
1632
    /* Convert to signed number */
1633
    if (sign) {
1634
        switch(size) {
1635
        case 1:
1636
            ret = (int8_t) ret;
1637
            break;
1638
        case 2:
1639
            ret = (int16_t) ret;
1640
            break;
1641
        case 4:
1642
            ret = (int32_t) ret;
1643
            break;
1644
        default:
1645
            break;
1646
        }
1647
    }
1648
#ifdef DEBUG_ASI
1649
    dump_asi("read ", last_addr, asi, size, ret);
1650
#endif
1651
    return ret;
1652
}
1653

    
1654
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1655
{
1656
#ifdef DEBUG_ASI
1657
    dump_asi("write", addr, asi, size, val);
1658
#endif
1659
    if (asi < 0x80)
1660
        raise_exception(TT_PRIV_ACT);
1661

    
1662
    helper_check_align(addr, size - 1);
1663
    address_mask(env, &addr);
1664

    
1665
    /* Convert to little endian */
1666
    switch (asi) {
1667
    case 0x88: // Primary LE
1668
    case 0x89: // Secondary LE
1669
        switch(size) {
1670
        case 2:
1671
            addr = bswap16(addr);
1672
            break;
1673
        case 4:
1674
            addr = bswap32(addr);
1675
            break;
1676
        case 8:
1677
            addr = bswap64(addr);
1678
            break;
1679
        default:
1680
            break;
1681
        }
1682
    default:
1683
        break;
1684
    }
1685

    
1686
    switch(asi) {
1687
    case 0x80: // Primary
1688
    case 0x88: // Primary LE
1689
        {
1690
            switch(size) {
1691
            case 1:
1692
                stb_raw(addr, val);
1693
                break;
1694
            case 2:
1695
                stw_raw(addr, val);
1696
                break;
1697
            case 4:
1698
                stl_raw(addr, val);
1699
                break;
1700
            case 8:
1701
            default:
1702
                stq_raw(addr, val);
1703
                break;
1704
            }
1705
        }
1706
        break;
1707
    case 0x81: // Secondary
1708
    case 0x89: // Secondary LE
1709
        // XXX
1710
        return;
1711

    
1712
    case 0x82: // Primary no-fault, RO
1713
    case 0x83: // Secondary no-fault, RO
1714
    case 0x8a: // Primary no-fault LE, RO
1715
    case 0x8b: // Secondary no-fault LE, RO
1716
    default:
1717
        do_unassigned_access(addr, 1, 0, 1, size);
1718
        return;
1719
    }
1720
}
1721

    
1722
#else /* CONFIG_USER_ONLY */
1723

    
1724
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1725
{
1726
    uint64_t ret = 0;
1727
#if defined(DEBUG_ASI)
1728
    target_ulong last_addr = addr;
1729
#endif
1730

    
1731
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1732
        || ((env->def->features & CPU_FEATURE_HYPV)
1733
            && asi >= 0x30 && asi < 0x80
1734
            && !(env->hpstate & HS_PRIV)))
1735
        raise_exception(TT_PRIV_ACT);
1736

    
1737
    helper_check_align(addr, size - 1);
1738
    switch (asi) {
1739
    case 0x82: // Primary no-fault
1740
    case 0x8a: // Primary no-fault LE
1741
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1742
#ifdef DEBUG_ASI
1743
            dump_asi("read ", last_addr, asi, size, ret);
1744
#endif
1745
            return 0;
1746
        }
1747
        // Fall through
1748
    case 0x10: // As if user primary
1749
    case 0x18: // As if user primary LE
1750
    case 0x80: // Primary
1751
    case 0x88: // Primary LE
1752
    case 0xe2: // UA2007 Primary block init
1753
    case 0xe3: // UA2007 Secondary block init
1754
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1755
            if ((env->def->features & CPU_FEATURE_HYPV)
1756
                && env->hpstate & HS_PRIV) {
1757
                switch(size) {
1758
                case 1:
1759
                    ret = ldub_hypv(addr);
1760
                    break;
1761
                case 2:
1762
                    ret = lduw_hypv(addr);
1763
                    break;
1764
                case 4:
1765
                    ret = ldl_hypv(addr);
1766
                    break;
1767
                default:
1768
                case 8:
1769
                    ret = ldq_hypv(addr);
1770
                    break;
1771
                }
1772
            } else {
1773
                switch(size) {
1774
                case 1:
1775
                    ret = ldub_kernel(addr);
1776
                    break;
1777
                case 2:
1778
                    ret = lduw_kernel(addr);
1779
                    break;
1780
                case 4:
1781
                    ret = ldl_kernel(addr);
1782
                    break;
1783
                default:
1784
                case 8:
1785
                    ret = ldq_kernel(addr);
1786
                    break;
1787
                }
1788
            }
1789
        } else {
1790
            switch(size) {
1791
            case 1:
1792
                ret = ldub_user(addr);
1793
                break;
1794
            case 2:
1795
                ret = lduw_user(addr);
1796
                break;
1797
            case 4:
1798
                ret = ldl_user(addr);
1799
                break;
1800
            default:
1801
            case 8:
1802
                ret = ldq_user(addr);
1803
                break;
1804
            }
1805
        }
1806
        break;
1807
    case 0x14: // Bypass
1808
    case 0x15: // Bypass, non-cacheable
1809
    case 0x1c: // Bypass LE
1810
    case 0x1d: // Bypass, non-cacheable LE
1811
        {
1812
            switch(size) {
1813
            case 1:
1814
                ret = ldub_phys(addr);
1815
                break;
1816
            case 2:
1817
                ret = lduw_phys(addr);
1818
                break;
1819
            case 4:
1820
                ret = ldl_phys(addr);
1821
                break;
1822
            default:
1823
            case 8:
1824
                ret = ldq_phys(addr);
1825
                break;
1826
            }
1827
            break;
1828
        }
1829
    case 0x24: // Nucleus quad LDD 128 bit atomic
1830
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1831
        //  Only ldda allowed
1832
        raise_exception(TT_ILL_INSN);
1833
        return 0;
1834
    case 0x83: // Secondary no-fault
1835
    case 0x8b: // Secondary no-fault LE
1836
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1837
#ifdef DEBUG_ASI
1838
            dump_asi("read ", last_addr, asi, size, ret);
1839
#endif
1840
            return 0;
1841
        }
1842
        // Fall through
1843
    case 0x04: // Nucleus
1844
    case 0x0c: // Nucleus Little Endian (LE)
1845
    case 0x11: // As if user secondary
1846
    case 0x19: // As if user secondary LE
1847
    case 0x4a: // UPA config
1848
    case 0x81: // Secondary
1849
    case 0x89: // Secondary LE
1850
        // XXX
1851
        break;
1852
    case 0x45: // LSU
1853
        ret = env->lsu;
1854
        break;
1855
    case 0x50: // I-MMU regs
1856
        {
1857
            int reg = (addr >> 3) & 0xf;
1858

    
1859
            if (reg == 0) {
1860
                // I-TSB Tag Target register
1861
                ret = ultrasparc_tag_target(env->immuregs[6]);
1862
            } else {
1863
                ret = env->immuregs[reg];
1864
            }
1865

    
1866
            break;
1867
        }
1868
    case 0x51: // I-MMU 8k TSB pointer
1869
        {
1870
            // env->immuregs[5] holds I-MMU TSB register value
1871
            // env->immuregs[6] holds I-MMU Tag Access register value
1872
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1873
                                         8*1024);
1874
            break;
1875
        }
1876
    case 0x52: // I-MMU 64k TSB pointer
1877
        {
1878
            // env->immuregs[5] holds I-MMU TSB register value
1879
            // env->immuregs[6] holds I-MMU Tag Access register value
1880
            ret = ultrasparc_tsb_pointer(env->immuregs[5], env->immuregs[6],
1881
                                         64*1024);
1882
            break;
1883
        }
1884
    case 0x55: // I-MMU data access
1885
        {
1886
            int reg = (addr >> 3) & 0x3f;
1887

    
1888
            ret = env->itlb_tte[reg];
1889
            break;
1890
        }
1891
    case 0x56: // I-MMU tag read
1892
        {
1893
            int reg = (addr >> 3) & 0x3f;
1894

    
1895
            ret = env->itlb_tag[reg];
1896
            break;
1897
        }
1898
    case 0x58: // D-MMU regs
1899
        {
1900
            int reg = (addr >> 3) & 0xf;
1901

    
1902
            if (reg == 0) {
1903
                // D-TSB Tag Target register
1904
                ret = ultrasparc_tag_target(env->dmmuregs[6]);
1905
            } else {
1906
                ret = env->dmmuregs[reg];
1907
            }
1908
            break;
1909
        }
1910
    case 0x59: // D-MMU 8k TSB pointer
1911
        {
1912
            // env->dmmuregs[5] holds D-MMU TSB register value
1913
            // env->dmmuregs[6] holds D-MMU Tag Access register value
1914
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1915
                                         8*1024);
1916
            break;
1917
        }
1918
    case 0x5a: // D-MMU 64k TSB pointer
1919
        {
1920
            // env->dmmuregs[5] holds D-MMU TSB register value
1921
            // env->dmmuregs[6] holds D-MMU Tag Access register value
1922
            ret = ultrasparc_tsb_pointer(env->dmmuregs[5], env->dmmuregs[6],
1923
                                         64*1024);
1924
            break;
1925
        }
1926
    case 0x5d: // D-MMU data access
1927
        {
1928
            int reg = (addr >> 3) & 0x3f;
1929

    
1930
            ret = env->dtlb_tte[reg];
1931
            break;
1932
        }
1933
    case 0x5e: // D-MMU tag read
1934
        {
1935
            int reg = (addr >> 3) & 0x3f;
1936

    
1937
            ret = env->dtlb_tag[reg];
1938
            break;
1939
        }
1940
    case 0x46: // D-cache data
1941
    case 0x47: // D-cache tag access
1942
    case 0x4b: // E-cache error enable
1943
    case 0x4c: // E-cache asynchronous fault status
1944
    case 0x4d: // E-cache asynchronous fault address
1945
    case 0x4e: // E-cache tag data
1946
    case 0x66: // I-cache instruction access
1947
    case 0x67: // I-cache tag access
1948
    case 0x6e: // I-cache predecode
1949
    case 0x6f: // I-cache LRU etc.
1950
    case 0x76: // E-cache tag
1951
    case 0x7e: // E-cache tag
1952
        break;
1953
    case 0x5b: // D-MMU data pointer
1954
    case 0x48: // Interrupt dispatch, RO
1955
    case 0x49: // Interrupt data receive
1956
    case 0x7f: // Incoming interrupt vector, RO
1957
        // XXX
1958
        break;
1959
    case 0x54: // I-MMU data in, WO
1960
    case 0x57: // I-MMU demap, WO
1961
    case 0x5c: // D-MMU data in, WO
1962
    case 0x5f: // D-MMU demap, WO
1963
    case 0x77: // Interrupt vector, WO
1964
    default:
1965
        do_unassigned_access(addr, 0, 0, 1, size);
1966
        ret = 0;
1967
        break;
1968
    }
1969

    
1970
    /* Convert from little endian */
1971
    switch (asi) {
1972
    case 0x0c: // Nucleus Little Endian (LE)
1973
    case 0x18: // As if user primary LE
1974
    case 0x19: // As if user secondary LE
1975
    case 0x1c: // Bypass LE
1976
    case 0x1d: // Bypass, non-cacheable LE
1977
    case 0x88: // Primary LE
1978
    case 0x89: // Secondary LE
1979
    case 0x8a: // Primary no-fault LE
1980
    case 0x8b: // Secondary no-fault LE
1981
        switch(size) {
1982
        case 2:
1983
            ret = bswap16(ret);
1984
            break;
1985
        case 4:
1986
            ret = bswap32(ret);
1987
            break;
1988
        case 8:
1989
            ret = bswap64(ret);
1990
            break;
1991
        default:
1992
            break;
1993
        }
1994
    default:
1995
        break;
1996
    }
1997

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

    
2020
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
2021
{
2022
#ifdef DEBUG_ASI
2023
    dump_asi("write", addr, asi, size, val);
2024
#endif
2025
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2026
        || ((env->def->features & CPU_FEATURE_HYPV)
2027
            && asi >= 0x30 && asi < 0x80
2028
            && !(env->hpstate & HS_PRIV)))
2029
        raise_exception(TT_PRIV_ACT);
2030

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

    
2058
    switch(asi) {
2059
    case 0x10: // As if user primary
2060
    case 0x18: // As if user primary LE
2061
    case 0x80: // Primary
2062
    case 0x88: // Primary LE
2063
    case 0xe2: // UA2007 Primary block init
2064
    case 0xe3: // UA2007 Secondary block init
2065
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
2066
            if ((env->def->features & CPU_FEATURE_HYPV)
2067
                && env->hpstate & HS_PRIV) {
2068
                switch(size) {
2069
                case 1:
2070
                    stb_hypv(addr, val);
2071
                    break;
2072
                case 2:
2073
                    stw_hypv(addr, val);
2074
                    break;
2075
                case 4:
2076
                    stl_hypv(addr, val);
2077
                    break;
2078
                case 8:
2079
                default:
2080
                    stq_hypv(addr, val);
2081
                    break;
2082
                }
2083
            } else {
2084
                switch(size) {
2085
                case 1:
2086
                    stb_kernel(addr, val);
2087
                    break;
2088
                case 2:
2089
                    stw_kernel(addr, val);
2090
                    break;
2091
                case 4:
2092
                    stl_kernel(addr, val);
2093
                    break;
2094
                case 8:
2095
                default:
2096
                    stq_kernel(addr, val);
2097
                    break;
2098
                }
2099
            }
2100
        } else {
2101
            switch(size) {
2102
            case 1:
2103
                stb_user(addr, val);
2104
                break;
2105
            case 2:
2106
                stw_user(addr, val);
2107
                break;
2108
            case 4:
2109
                stl_user(addr, val);
2110
                break;
2111
            case 8:
2112
            default:
2113
                stq_user(addr, val);
2114
                break;
2115
            }
2116
        }
2117
        break;
2118
    case 0x14: // Bypass
2119
    case 0x15: // Bypass, non-cacheable
2120
    case 0x1c: // Bypass LE
2121
    case 0x1d: // Bypass, non-cacheable LE
2122
        {
2123
            switch(size) {
2124
            case 1:
2125
                stb_phys(addr, val);
2126
                break;
2127
            case 2:
2128
                stw_phys(addr, val);
2129
                break;
2130
            case 4:
2131
                stl_phys(addr, val);
2132
                break;
2133
            case 8:
2134
            default:
2135
                stq_phys(addr, val);
2136
                break;
2137
            }
2138
        }
2139
        return;
2140
    case 0x24: // Nucleus quad LDD 128 bit atomic
2141
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2142
        //  Only ldda allowed
2143
        raise_exception(TT_ILL_INSN);
2144
        return;
2145
    case 0x04: // Nucleus
2146
    case 0x0c: // Nucleus Little Endian (LE)
2147
    case 0x11: // As if user secondary
2148
    case 0x19: // As if user secondary LE
2149
    case 0x4a: // UPA config
2150
    case 0x81: // Secondary
2151
    case 0x89: // Secondary LE
2152
        // XXX
2153
        return;
2154
    case 0x45: // LSU
2155
        {
2156
            uint64_t oldreg;
2157

    
2158
            oldreg = env->lsu;
2159
            env->lsu = val & (DMMU_E | IMMU_E);
2160
            // Mappings generated during D/I MMU disabled mode are
2161
            // invalid in normal mode
2162
            if (oldreg != env->lsu) {
2163
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
2164
                            oldreg, env->lsu);
2165
#ifdef DEBUG_MMU
2166
                dump_mmu(env);
2167
#endif
2168
                tlb_flush(env, 1);
2169
            }
2170
            return;
2171
        }
2172
    case 0x50: // I-MMU regs
2173
        {
2174
            int reg = (addr >> 3) & 0xf;
2175
            uint64_t oldreg;
2176

    
2177
            oldreg = env->immuregs[reg];
2178
            switch(reg) {
2179
            case 0: // RO
2180
            case 4:
2181
                return;
2182
            case 1: // Not in I-MMU
2183
            case 2:
2184
            case 7:
2185
            case 8:
2186
                return;
2187
            case 3: // SFSR
2188
                if ((val & 1) == 0)
2189
                    val = 0; // Clear SFSR
2190
                break;
2191
            case 5: // TSB access
2192
            case 6: // Tag access
2193
            default:
2194
                break;
2195
            }
2196
            env->immuregs[reg] = val;
2197
            if (oldreg != env->immuregs[reg]) {
2198
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2199
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
2200
            }
2201
#ifdef DEBUG_MMU
2202
            dump_mmu(env);
2203
#endif
2204
            return;
2205
        }
2206
    case 0x54: // I-MMU data in
2207
        {
2208
            unsigned int i;
2209

    
2210
            // Try finding an invalid entry
2211
            for (i = 0; i < 64; i++) {
2212
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
2213
                    env->itlb_tag[i] = env->immuregs[6];
2214
                    env->itlb_tte[i] = val;
2215
                    return;
2216
                }
2217
            }
2218
            // Try finding an unlocked entry
2219
            for (i = 0; i < 64; i++) {
2220
                if ((env->itlb_tte[i] & 0x40) == 0) {
2221
                    env->itlb_tag[i] = env->immuregs[6];
2222
                    env->itlb_tte[i] = val;
2223
                    return;
2224
                }
2225
            }
2226
            // error state?
2227
            return;
2228
        }
2229
    case 0x55: // I-MMU data access
2230
        {
2231
            // TODO: auto demap
2232

    
2233
            unsigned int i = (addr >> 3) & 0x3f;
2234

    
2235
            env->itlb_tag[i] = env->immuregs[6];
2236
            env->itlb_tte[i] = val;
2237
            return;
2238
        }
2239
    case 0x57: // I-MMU demap
2240
        {
2241
            unsigned int i;
2242

    
2243
            for (i = 0; i < 64; i++) {
2244
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
2245
                    target_ulong mask = 0xffffffffffffe000ULL;
2246

    
2247
                    mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
2248
                    if ((val & mask) == (env->itlb_tag[i] & mask)) {
2249
                        env->itlb_tag[i] = 0;
2250
                        env->itlb_tte[i] = 0;
2251
                    }
2252
                    return;
2253
                }
2254
            }
2255
        }
2256
        return;
2257
    case 0x58: // D-MMU regs
2258
        {
2259
            int reg = (addr >> 3) & 0xf;
2260
            uint64_t oldreg;
2261

    
2262
            oldreg = env->dmmuregs[reg];
2263
            switch(reg) {
2264
            case 0: // RO
2265
            case 4:
2266
                return;
2267
            case 3: // SFSR
2268
                if ((val & 1) == 0) {
2269
                    val = 0; // Clear SFSR, Fault address
2270
                    env->dmmuregs[4] = 0;
2271
                }
2272
                env->dmmuregs[reg] = val;
2273
                break;
2274
            case 1: // Primary context
2275
            case 2: // Secondary context
2276
            case 5: // TSB access
2277
            case 6: // Tag access
2278
            case 7: // Virtual Watchpoint
2279
            case 8: // Physical Watchpoint
2280
            default:
2281
                break;
2282
            }
2283
            env->dmmuregs[reg] = val;
2284
            if (oldreg != env->dmmuregs[reg]) {
2285
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2286
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2287
            }
2288
#ifdef DEBUG_MMU
2289
            dump_mmu(env);
2290
#endif
2291
            return;
2292
        }
2293
    case 0x5c: // D-MMU data in
2294
        {
2295
            unsigned int i;
2296

    
2297
            // Try finding an invalid entry
2298
            for (i = 0; i < 64; i++) {
2299
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2300
                    env->dtlb_tag[i] = env->dmmuregs[6];
2301
                    env->dtlb_tte[i] = val;
2302
                    return;
2303
                }
2304
            }
2305
            // Try finding an unlocked entry
2306
            for (i = 0; i < 64; i++) {
2307
                if ((env->dtlb_tte[i] & 0x40) == 0) {
2308
                    env->dtlb_tag[i] = env->dmmuregs[6];
2309
                    env->dtlb_tte[i] = val;
2310
                    return;
2311
                }
2312
            }
2313
            // error state?
2314
            return;
2315
        }
2316
    case 0x5d: // D-MMU data access
2317
        {
2318
            unsigned int i = (addr >> 3) & 0x3f;
2319

    
2320
            env->dtlb_tag[i] = env->dmmuregs[6];
2321
            env->dtlb_tte[i] = val;
2322
            return;
2323
        }
2324
    case 0x5f: // D-MMU demap
2325
        {
2326
            unsigned int i;
2327

    
2328
            for (i = 0; i < 64; i++) {
2329
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
2330
                    target_ulong mask = 0xffffffffffffe000ULL;
2331

    
2332
                    mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
2333
                    if ((val & mask) == (env->dtlb_tag[i] & mask)) {
2334
                        env->dtlb_tag[i] = 0;
2335
                        env->dtlb_tte[i] = 0;
2336
                    }
2337
                    return;
2338
                }
2339
            }
2340
        }
2341
        return;
2342
    case 0x49: // Interrupt data receive
2343
        // XXX
2344
        return;
2345
    case 0x46: // D-cache data
2346
    case 0x47: // D-cache tag access
2347
    case 0x4b: // E-cache error enable
2348
    case 0x4c: // E-cache asynchronous fault status
2349
    case 0x4d: // E-cache asynchronous fault address
2350
    case 0x4e: // E-cache tag data
2351
    case 0x66: // I-cache instruction access
2352
    case 0x67: // I-cache tag access
2353
    case 0x6e: // I-cache predecode
2354
    case 0x6f: // I-cache LRU etc.
2355
    case 0x76: // E-cache tag
2356
    case 0x7e: // E-cache tag
2357
        return;
2358
    case 0x51: // I-MMU 8k TSB pointer, RO
2359
    case 0x52: // I-MMU 64k TSB pointer, RO
2360
    case 0x56: // I-MMU tag read, RO
2361
    case 0x59: // D-MMU 8k TSB pointer, RO
2362
    case 0x5a: // D-MMU 64k TSB pointer, RO
2363
    case 0x5b: // D-MMU data pointer, RO
2364
    case 0x5e: // D-MMU tag read, RO
2365
    case 0x48: // Interrupt dispatch, RO
2366
    case 0x7f: // Incoming interrupt vector, RO
2367
    case 0x82: // Primary no-fault, RO
2368
    case 0x83: // Secondary no-fault, RO
2369
    case 0x8a: // Primary no-fault LE, RO
2370
    case 0x8b: // Secondary no-fault LE, RO
2371
    default:
2372
        do_unassigned_access(addr, 1, 0, 1, size);
2373
        return;
2374
    }
2375
}
2376
#endif /* CONFIG_USER_ONLY */
2377

    
2378
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2379
{
2380
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2381
        || ((env->def->features & CPU_FEATURE_HYPV)
2382
            && asi >= 0x30 && asi < 0x80
2383
            && !(env->hpstate & HS_PRIV)))
2384
        raise_exception(TT_PRIV_ACT);
2385

    
2386
    switch (asi) {
2387
    case 0x24: // Nucleus quad LDD 128 bit atomic
2388
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2389
        helper_check_align(addr, 0xf);
2390
        if (rd == 0) {
2391
            env->gregs[1] = ldq_kernel(addr + 8);
2392
            if (asi == 0x2c)
2393
                bswap64s(&env->gregs[1]);
2394
        } else if (rd < 8) {
2395
            env->gregs[rd] = ldq_kernel(addr);
2396
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2397
            if (asi == 0x2c) {
2398
                bswap64s(&env->gregs[rd]);
2399
                bswap64s(&env->gregs[rd + 1]);
2400
            }
2401
        } else {
2402
            env->regwptr[rd] = ldq_kernel(addr);
2403
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2404
            if (asi == 0x2c) {
2405
                bswap64s(&env->regwptr[rd]);
2406
                bswap64s(&env->regwptr[rd + 1]);
2407
            }
2408
        }
2409
        break;
2410
    default:
2411
        helper_check_align(addr, 0x3);
2412
        if (rd == 0)
2413
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2414
        else if (rd < 8) {
2415
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2416
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2417
        } else {
2418
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2419
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2420
        }
2421
        break;
2422
    }
2423
}
2424

    
2425
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2426
{
2427
    unsigned int i;
2428
    target_ulong val;
2429

    
2430
    helper_check_align(addr, 3);
2431
    switch (asi) {
2432
    case 0xf0: // Block load primary
2433
    case 0xf1: // Block load secondary
2434
    case 0xf8: // Block load primary LE
2435
    case 0xf9: // Block load secondary LE
2436
        if (rd & 7) {
2437
            raise_exception(TT_ILL_INSN);
2438
            return;
2439
        }
2440
        helper_check_align(addr, 0x3f);
2441
        for (i = 0; i < 16; i++) {
2442
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2443
                                                         0);
2444
            addr += 4;
2445
        }
2446

    
2447
        return;
2448
    default:
2449
        break;
2450
    }
2451

    
2452
    val = helper_ld_asi(addr, asi, size, 0);
2453
    switch(size) {
2454
    default:
2455
    case 4:
2456
        *((uint32_t *)&env->fpr[rd]) = val;
2457
        break;
2458
    case 8:
2459
        *((int64_t *)&DT0) = val;
2460
        break;
2461
    case 16:
2462
        // XXX
2463
        break;
2464
    }
2465
}
2466

    
2467
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2468
{
2469
    unsigned int i;
2470
    target_ulong val = 0;
2471

    
2472
    helper_check_align(addr, 3);
2473
    switch (asi) {
2474
    case 0xe0: // UA2007 Block commit store primary (cache flush)
2475
    case 0xe1: // UA2007 Block commit store secondary (cache flush)
2476
    case 0xf0: // Block store primary
2477
    case 0xf1: // Block store secondary
2478
    case 0xf8: // Block store primary LE
2479
    case 0xf9: // Block store secondary LE
2480
        if (rd & 7) {
2481
            raise_exception(TT_ILL_INSN);
2482
            return;
2483
        }
2484
        helper_check_align(addr, 0x3f);
2485
        for (i = 0; i < 16; i++) {
2486
            val = *(uint32_t *)&env->fpr[rd++];
2487
            helper_st_asi(addr, val, asi & 0x8f, 4);
2488
            addr += 4;
2489
        }
2490

    
2491
        return;
2492
    default:
2493
        break;
2494
    }
2495

    
2496
    switch(size) {
2497
    default:
2498
    case 4:
2499
        val = *((uint32_t *)&env->fpr[rd]);
2500
        break;
2501
    case 8:
2502
        val = *((int64_t *)&DT0);
2503
        break;
2504
    case 16:
2505
        // XXX
2506
        break;
2507
    }
2508
    helper_st_asi(addr, val, asi, size);
2509
}
2510

    
2511
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2512
                            target_ulong val2, uint32_t asi)
2513
{
2514
    target_ulong ret;
2515

    
2516
    val2 &= 0xffffffffUL;
2517
    ret = helper_ld_asi(addr, asi, 4, 0);
2518
    ret &= 0xffffffffUL;
2519
    if (val2 == ret)
2520
        helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
2521
    return ret;
2522
}
2523

    
2524
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2525
                             target_ulong val2, uint32_t asi)
2526
{
2527
    target_ulong ret;
2528

    
2529
    ret = helper_ld_asi(addr, asi, 8, 0);
2530
    if (val2 == ret)
2531
        helper_st_asi(addr, val1, asi, 8);
2532
    return ret;
2533
}
2534
#endif /* TARGET_SPARC64 */
2535

    
2536
#ifndef TARGET_SPARC64
2537
void helper_rett(void)
2538
{
2539
    unsigned int cwp;
2540

    
2541
    if (env->psret == 1)
2542
        raise_exception(TT_ILL_INSN);
2543

    
2544
    env->psret = 1;
2545
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2546
    if (env->wim & (1 << cwp)) {
2547
        raise_exception(TT_WIN_UNF);
2548
    }
2549
    set_cwp(cwp);
2550
    env->psrs = env->psrps;
2551
}
2552
#endif
2553

    
2554
target_ulong helper_udiv(target_ulong a, target_ulong b)
2555
{
2556
    uint64_t x0;
2557
    uint32_t x1;
2558

    
2559
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2560
    x1 = b;
2561

    
2562
    if (x1 == 0) {
2563
        raise_exception(TT_DIV_ZERO);
2564
    }
2565

    
2566
    x0 = x0 / x1;
2567
    if (x0 > 0xffffffff) {
2568
        env->cc_src2 = 1;
2569
        return 0xffffffff;
2570
    } else {
2571
        env->cc_src2 = 0;
2572
        return x0;
2573
    }
2574
}
2575

    
2576
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2577
{
2578
    int64_t x0;
2579
    int32_t x1;
2580

    
2581
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2582
    x1 = b;
2583

    
2584
    if (x1 == 0) {
2585
        raise_exception(TT_DIV_ZERO);
2586
    }
2587

    
2588
    x0 = x0 / x1;
2589
    if ((int32_t) x0 != x0) {
2590
        env->cc_src2 = 1;
2591
        return x0 < 0? 0x80000000: 0x7fffffff;
2592
    } else {
2593
        env->cc_src2 = 0;
2594
        return x0;
2595
    }
2596
}
2597

    
2598
void helper_stdf(target_ulong addr, int mem_idx)
2599
{
2600
    helper_check_align(addr, 7);
2601
#if !defined(CONFIG_USER_ONLY)
2602
    switch (mem_idx) {
2603
    case 0:
2604
        stfq_user(addr, DT0);
2605
        break;
2606
    case 1:
2607
        stfq_kernel(addr, DT0);
2608
        break;
2609
#ifdef TARGET_SPARC64
2610
    case 2:
2611
        stfq_hypv(addr, DT0);
2612
        break;
2613
#endif
2614
    default:
2615
        break;
2616
    }
2617
#else
2618
    address_mask(env, &addr);
2619
    stfq_raw(addr, DT0);
2620
#endif
2621
}
2622

    
2623
void helper_lddf(target_ulong addr, int mem_idx)
2624
{
2625
    helper_check_align(addr, 7);
2626
#if !defined(CONFIG_USER_ONLY)
2627
    switch (mem_idx) {
2628
    case 0:
2629
        DT0 = ldfq_user(addr);
2630
        break;
2631
    case 1:
2632
        DT0 = ldfq_kernel(addr);
2633
        break;
2634
#ifdef TARGET_SPARC64
2635
    case 2:
2636
        DT0 = ldfq_hypv(addr);
2637
        break;
2638
#endif
2639
    default:
2640
        break;
2641
    }
2642
#else
2643
    address_mask(env, &addr);
2644
    DT0 = ldfq_raw(addr);
2645
#endif
2646
}
2647

    
2648
void helper_ldqf(target_ulong addr, int mem_idx)
2649
{
2650
    // XXX add 128 bit load
2651
    CPU_QuadU u;
2652

    
2653
    helper_check_align(addr, 7);
2654
#if !defined(CONFIG_USER_ONLY)
2655
    switch (mem_idx) {
2656
    case 0:
2657
        u.ll.upper = ldq_user(addr);
2658
        u.ll.lower = ldq_user(addr + 8);
2659
        QT0 = u.q;
2660
        break;
2661
    case 1:
2662
        u.ll.upper = ldq_kernel(addr);
2663
        u.ll.lower = ldq_kernel(addr + 8);
2664
        QT0 = u.q;
2665
        break;
2666
#ifdef TARGET_SPARC64
2667
    case 2:
2668
        u.ll.upper = ldq_hypv(addr);
2669
        u.ll.lower = ldq_hypv(addr + 8);
2670
        QT0 = u.q;
2671
        break;
2672
#endif
2673
    default:
2674
        break;
2675
    }
2676
#else
2677
    address_mask(env, &addr);
2678
    u.ll.upper = ldq_raw(addr);
2679
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2680
    QT0 = u.q;
2681
#endif
2682
}
2683

    
2684
void helper_stqf(target_ulong addr, int mem_idx)
2685
{
2686
    // XXX add 128 bit store
2687
    CPU_QuadU u;
2688

    
2689
    helper_check_align(addr, 7);
2690
#if !defined(CONFIG_USER_ONLY)
2691
    switch (mem_idx) {
2692
    case 0:
2693
        u.q = QT0;
2694
        stq_user(addr, u.ll.upper);
2695
        stq_user(addr + 8, u.ll.lower);
2696
        break;
2697
    case 1:
2698
        u.q = QT0;
2699
        stq_kernel(addr, u.ll.upper);
2700
        stq_kernel(addr + 8, u.ll.lower);
2701
        break;
2702
#ifdef TARGET_SPARC64
2703
    case 2:
2704
        u.q = QT0;
2705
        stq_hypv(addr, u.ll.upper);
2706
        stq_hypv(addr + 8, u.ll.lower);
2707
        break;
2708
#endif
2709
    default:
2710
        break;
2711
    }
2712
#else
2713
    u.q = QT0;
2714
    address_mask(env, &addr);
2715
    stq_raw(addr, u.ll.upper);
2716
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2717
#endif
2718
}
2719

    
2720
static inline void set_fsr(void)
2721
{
2722
    int rnd_mode;
2723

    
2724
    switch (env->fsr & FSR_RD_MASK) {
2725
    case FSR_RD_NEAREST:
2726
        rnd_mode = float_round_nearest_even;
2727
        break;
2728
    default:
2729
    case FSR_RD_ZERO:
2730
        rnd_mode = float_round_to_zero;
2731
        break;
2732
    case FSR_RD_POS:
2733
        rnd_mode = float_round_up;
2734
        break;
2735
    case FSR_RD_NEG:
2736
        rnd_mode = float_round_down;
2737
        break;
2738
    }
2739
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2740
}
2741

    
2742
void helper_ldfsr(uint32_t new_fsr)
2743
{
2744
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
2745
    set_fsr();
2746
}
2747

    
2748
#ifdef TARGET_SPARC64
2749
void helper_ldxfsr(uint64_t new_fsr)
2750
{
2751
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
2752
    set_fsr();
2753
}
2754
#endif
2755

    
2756
void helper_debug(void)
2757
{
2758
    env->exception_index = EXCP_DEBUG;
2759
    cpu_loop_exit();
2760
}
2761

    
2762
#ifndef TARGET_SPARC64
2763
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2764
   handling ? */
2765
void helper_save(void)
2766
{
2767
    uint32_t cwp;
2768

    
2769
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2770
    if (env->wim & (1 << cwp)) {
2771
        raise_exception(TT_WIN_OVF);
2772
    }
2773
    set_cwp(cwp);
2774
}
2775

    
2776
void helper_restore(void)
2777
{
2778
    uint32_t cwp;
2779

    
2780
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2781
    if (env->wim & (1 << cwp)) {
2782
        raise_exception(TT_WIN_UNF);
2783
    }
2784
    set_cwp(cwp);
2785
}
2786

    
2787
void helper_wrpsr(target_ulong new_psr)
2788
{
2789
    if ((new_psr & PSR_CWP) >= env->nwindows)
2790
        raise_exception(TT_ILL_INSN);
2791
    else
2792
        PUT_PSR(env, new_psr);
2793
}
2794

    
2795
target_ulong helper_rdpsr(void)
2796
{
2797
    return GET_PSR(env);
2798
}
2799

    
2800
#else
2801
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2802
   handling ? */
2803
void helper_save(void)
2804
{
2805
    uint32_t cwp;
2806

    
2807
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2808
    if (env->cansave == 0) {
2809
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2810
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2811
                                    ((env->wstate & 0x7) << 2)));
2812
    } else {
2813
        if (env->cleanwin - env->canrestore == 0) {
2814
            // XXX Clean windows without trap
2815
            raise_exception(TT_CLRWIN);
2816
        } else {
2817
            env->cansave--;
2818
            env->canrestore++;
2819
            set_cwp(cwp);
2820
        }
2821
    }
2822
}
2823

    
2824
void helper_restore(void)
2825
{
2826
    uint32_t cwp;
2827

    
2828
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2829
    if (env->canrestore == 0) {
2830
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2831
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2832
                                   ((env->wstate & 0x7) << 2)));
2833
    } else {
2834
        env->cansave++;
2835
        env->canrestore--;
2836
        set_cwp(cwp);
2837
    }
2838
}
2839

    
2840
void helper_flushw(void)
2841
{
2842
    if (env->cansave != env->nwindows - 2) {
2843
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2844
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2845
                                    ((env->wstate & 0x7) << 2)));
2846
    }
2847
}
2848

    
2849
void helper_saved(void)
2850
{
2851
    env->cansave++;
2852
    if (env->otherwin == 0)
2853
        env->canrestore--;
2854
    else
2855
        env->otherwin--;
2856
}
2857

    
2858
void helper_restored(void)
2859
{
2860
    env->canrestore++;
2861
    if (env->cleanwin < env->nwindows - 1)
2862
        env->cleanwin++;
2863
    if (env->otherwin == 0)
2864
        env->cansave--;
2865
    else
2866
        env->otherwin--;
2867
}
2868

    
2869
target_ulong helper_rdccr(void)
2870
{
2871
    return GET_CCR(env);
2872
}
2873

    
2874
void helper_wrccr(target_ulong new_ccr)
2875
{
2876
    PUT_CCR(env, new_ccr);
2877
}
2878

    
2879
// CWP handling is reversed in V9, but we still use the V8 register
2880
// order.
2881
target_ulong helper_rdcwp(void)
2882
{
2883
    return GET_CWP64(env);
2884
}
2885

    
2886
void helper_wrcwp(target_ulong new_cwp)
2887
{
2888
    PUT_CWP64(env, new_cwp);
2889
}
2890

    
2891
// This function uses non-native bit order
2892
#define GET_FIELD(X, FROM, TO)                                  \
2893
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2894

    
2895
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2896
#define GET_FIELD_SP(X, FROM, TO)               \
2897
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2898

    
2899
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2900
{
2901
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2902
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2903
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2904
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2905
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2906
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2907
        (((pixel_addr >> 55) & 1) << 4) |
2908
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2909
        GET_FIELD_SP(pixel_addr, 11, 12);
2910
}
2911

    
2912
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2913
{
2914
    uint64_t tmp;
2915

    
2916
    tmp = addr + offset;
2917
    env->gsr &= ~7ULL;
2918
    env->gsr |= tmp & 7ULL;
2919
    return tmp & ~7ULL;
2920
}
2921

    
2922
target_ulong helper_popc(target_ulong val)
2923
{
2924
    return ctpop64(val);
2925
}
2926

    
2927
static inline uint64_t *get_gregset(uint64_t pstate)
2928
{
2929
    switch (pstate) {
2930
    default:
2931
    case 0:
2932
        return env->bgregs;
2933
    case PS_AG:
2934
        return env->agregs;
2935
    case PS_MG:
2936
        return env->mgregs;
2937
    case PS_IG:
2938
        return env->igregs;
2939
    }
2940
}
2941

    
2942
static inline void change_pstate(uint64_t new_pstate)
2943
{
2944
    uint64_t pstate_regs, new_pstate_regs;
2945
    uint64_t *src, *dst;
2946

    
2947
    pstate_regs = env->pstate & 0xc01;
2948
    new_pstate_regs = new_pstate & 0xc01;
2949
    if (new_pstate_regs != pstate_regs) {
2950
        // Switch global register bank
2951
        src = get_gregset(new_pstate_regs);
2952
        dst = get_gregset(pstate_regs);
2953
        memcpy32(dst, env->gregs);
2954
        memcpy32(env->gregs, src);
2955
    }
2956
    env->pstate = new_pstate;
2957
}
2958

    
2959
void helper_wrpstate(target_ulong new_state)
2960
{
2961
    if (!(env->def->features & CPU_FEATURE_GL))
2962
        change_pstate(new_state & 0xf3f);
2963
}
2964

    
2965
void helper_done(void)
2966
{
2967
    env->pc = env->tsptr->tpc;
2968
    env->npc = env->tsptr->tnpc + 4;
2969
    PUT_CCR(env, env->tsptr->tstate >> 32);
2970
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2971
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2972
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2973
    env->tl--;
2974
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2975
}
2976

    
2977
void helper_retry(void)
2978
{
2979
    env->pc = env->tsptr->tpc;
2980
    env->npc = env->tsptr->tnpc;
2981
    PUT_CCR(env, env->tsptr->tstate >> 32);
2982
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2983
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2984
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2985
    env->tl--;
2986
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2987
}
2988

    
2989
void helper_set_softint(uint64_t value)
2990
{
2991
    env->softint |= (uint32_t)value;
2992
}
2993

    
2994
void helper_clear_softint(uint64_t value)
2995
{
2996
    env->softint &= (uint32_t)~value;
2997
}
2998

    
2999
void helper_write_softint(uint64_t value)
3000
{
3001
    env->softint = (uint32_t)value;
3002
}
3003
#endif
3004

    
3005
void helper_flush(target_ulong addr)
3006
{
3007
    addr &= ~7;
3008
    tb_invalidate_page_range(addr, addr + 8);
3009
}
3010

    
3011
#ifdef TARGET_SPARC64
3012
#ifdef DEBUG_PCALL
3013
static const char * const excp_names[0x80] = {
3014
    [TT_TFAULT] = "Instruction Access Fault",
3015
    [TT_TMISS] = "Instruction Access MMU Miss",
3016
    [TT_CODE_ACCESS] = "Instruction Access Error",
3017
    [TT_ILL_INSN] = "Illegal Instruction",
3018
    [TT_PRIV_INSN] = "Privileged Instruction",
3019
    [TT_NFPU_INSN] = "FPU Disabled",
3020
    [TT_FP_EXCP] = "FPU Exception",
3021
    [TT_TOVF] = "Tag Overflow",
3022
    [TT_CLRWIN] = "Clean Windows",
3023
    [TT_DIV_ZERO] = "Division By Zero",
3024
    [TT_DFAULT] = "Data Access Fault",
3025
    [TT_DMISS] = "Data Access MMU Miss",
3026
    [TT_DATA_ACCESS] = "Data Access Error",
3027
    [TT_DPROT] = "Data Protection Error",
3028
    [TT_UNALIGNED] = "Unaligned Memory Access",
3029
    [TT_PRIV_ACT] = "Privileged Action",
3030
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3031
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3032
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3033
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3034
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3035
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3036
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3037
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3038
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3039
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3040
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3041
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3042
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3043
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3044
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3045
};
3046
#endif
3047

    
3048
void do_interrupt(CPUState *env)
3049
{
3050
    int intno = env->exception_index;
3051

    
3052
#ifdef DEBUG_PCALL
3053
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3054
        static int count;
3055
        const char *name;
3056

    
3057
        if (intno < 0 || intno >= 0x180)
3058
            name = "Unknown";
3059
        else if (intno >= 0x100)
3060
            name = "Trap Instruction";
3061
        else if (intno >= 0xc0)
3062
            name = "Window Fill";
3063
        else if (intno >= 0x80)
3064
            name = "Window Spill";
3065
        else {
3066
            name = excp_names[intno];
3067
            if (!name)
3068
                name = "Unknown";
3069
        }
3070

    
3071
        qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
3072
                " SP=%016" PRIx64 "\n",
3073
                count, name, intno,
3074
                env->pc,
3075
                env->npc, env->regwptr[6]);
3076
        log_cpu_state(env, 0);
3077
#if 0
3078
        {
3079
            int i;
3080
            uint8_t *ptr;
3081

3082
            qemu_log("       code=");
3083
            ptr = (uint8_t *)env->pc;
3084
            for(i = 0; i < 16; i++) {
3085
                qemu_log(" %02x", ldub(ptr + i));
3086
            }
3087
            qemu_log("\n");
3088
        }
3089
#endif
3090
        count++;
3091
    }
3092
#endif
3093
#if !defined(CONFIG_USER_ONLY)
3094
    if (env->tl >= env->maxtl) {
3095
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
3096
                  " Error state", env->exception_index, env->tl, env->maxtl);
3097
        return;
3098
    }
3099
#endif
3100
    if (env->tl < env->maxtl - 1) {
3101
        env->tl++;
3102
    } else {
3103
        env->pstate |= PS_RED;
3104
        if (env->tl < env->maxtl)
3105
            env->tl++;
3106
    }
3107
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
3108
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
3109
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
3110
        GET_CWP64(env);
3111
    env->tsptr->tpc = env->pc;
3112
    env->tsptr->tnpc = env->npc;
3113
    env->tsptr->tt = intno;
3114
    if (!(env->def->features & CPU_FEATURE_GL)) {
3115
        switch (intno) {
3116
        case TT_IVEC:
3117
            change_pstate(PS_PEF | PS_PRIV | PS_IG);
3118
            break;
3119
        case TT_TFAULT:
3120
        case TT_TMISS:
3121
        case TT_DFAULT:
3122
        case TT_DMISS:
3123
        case TT_DPROT:
3124
            change_pstate(PS_PEF | PS_PRIV | PS_MG);
3125
            break;
3126
        default:
3127
            change_pstate(PS_PEF | PS_PRIV | PS_AG);
3128
            break;
3129
        }
3130
    }
3131
    if (intno == TT_CLRWIN)
3132
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
3133
    else if ((intno & 0x1c0) == TT_SPILL)
3134
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
3135
    else if ((intno & 0x1c0) == TT_FILL)
3136
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
3137
    env->tbr &= ~0x7fffULL;
3138
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
3139
    env->pc = env->tbr;
3140
    env->npc = env->pc + 4;
3141
    env->exception_index = 0;
3142
}
3143
#else
3144
#ifdef DEBUG_PCALL
3145
static const char * const excp_names[0x80] = {
3146
    [TT_TFAULT] = "Instruction Access Fault",
3147
    [TT_ILL_INSN] = "Illegal Instruction",
3148
    [TT_PRIV_INSN] = "Privileged Instruction",
3149
    [TT_NFPU_INSN] = "FPU Disabled",
3150
    [TT_WIN_OVF] = "Window Overflow",
3151
    [TT_WIN_UNF] = "Window Underflow",
3152
    [TT_UNALIGNED] = "Unaligned Memory Access",
3153
    [TT_FP_EXCP] = "FPU Exception",
3154
    [TT_DFAULT] = "Data Access Fault",
3155
    [TT_TOVF] = "Tag Overflow",
3156
    [TT_EXTINT | 0x1] = "External Interrupt 1",
3157
    [TT_EXTINT | 0x2] = "External Interrupt 2",
3158
    [TT_EXTINT | 0x3] = "External Interrupt 3",
3159
    [TT_EXTINT | 0x4] = "External Interrupt 4",
3160
    [TT_EXTINT | 0x5] = "External Interrupt 5",
3161
    [TT_EXTINT | 0x6] = "External Interrupt 6",
3162
    [TT_EXTINT | 0x7] = "External Interrupt 7",
3163
    [TT_EXTINT | 0x8] = "External Interrupt 8",
3164
    [TT_EXTINT | 0x9] = "External Interrupt 9",
3165
    [TT_EXTINT | 0xa] = "External Interrupt 10",
3166
    [TT_EXTINT | 0xb] = "External Interrupt 11",
3167
    [TT_EXTINT | 0xc] = "External Interrupt 12",
3168
    [TT_EXTINT | 0xd] = "External Interrupt 13",
3169
    [TT_EXTINT | 0xe] = "External Interrupt 14",
3170
    [TT_EXTINT | 0xf] = "External Interrupt 15",
3171
    [TT_TOVF] = "Tag Overflow",
3172
    [TT_CODE_ACCESS] = "Instruction Access Error",
3173
    [TT_DATA_ACCESS] = "Data Access Error",
3174
    [TT_DIV_ZERO] = "Division By Zero",
3175
    [TT_NCP_INSN] = "Coprocessor Disabled",
3176
};
3177
#endif
3178

    
3179
void do_interrupt(CPUState *env)
3180
{
3181
    int cwp, intno = env->exception_index;
3182

    
3183
#ifdef DEBUG_PCALL
3184
    if (qemu_loglevel_mask(CPU_LOG_INT)) {
3185
        static int count;
3186
        const char *name;
3187

    
3188
        if (intno < 0 || intno >= 0x100)
3189
            name = "Unknown";
3190
        else if (intno >= 0x80)
3191
            name = "Trap Instruction";
3192
        else {
3193
            name = excp_names[intno];
3194
            if (!name)
3195
                name = "Unknown";
3196
        }
3197

    
3198
        qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
3199
                count, name, intno,
3200
                env->pc,
3201
                env->npc, env->regwptr[6]);
3202
        log_cpu_state(env, 0);
3203
#if 0
3204
        {
3205
            int i;
3206
            uint8_t *ptr;
3207

3208
            qemu_log("       code=");
3209
            ptr = (uint8_t *)env->pc;
3210
            for(i = 0; i < 16; i++) {
3211
                qemu_log(" %02x", ldub(ptr + i));
3212
            }
3213
            qemu_log("\n");
3214
        }
3215
#endif
3216
        count++;
3217
    }
3218
#endif
3219
#if !defined(CONFIG_USER_ONLY)
3220
    if (env->psret == 0) {
3221
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
3222
                  env->exception_index);
3223
        return;
3224
    }
3225
#endif
3226
    env->psret = 0;
3227
    cwp = cpu_cwp_dec(env, env->cwp - 1);
3228
    cpu_set_cwp(env, cwp);
3229
    env->regwptr[9] = env->pc;
3230
    env->regwptr[10] = env->npc;
3231
    env->psrps = env->psrs;
3232
    env->psrs = 1;
3233
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
3234
    env->pc = env->tbr;
3235
    env->npc = env->pc + 4;
3236
    env->exception_index = 0;
3237
}
3238
#endif
3239

    
3240
#if !defined(CONFIG_USER_ONLY)
3241

    
3242
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3243
                                void *retaddr);
3244

    
3245
#define MMUSUFFIX _mmu
3246
#define ALIGNED_ONLY
3247

    
3248
#define SHIFT 0
3249
#include "softmmu_template.h"
3250

    
3251
#define SHIFT 1
3252
#include "softmmu_template.h"
3253

    
3254
#define SHIFT 2
3255
#include "softmmu_template.h"
3256

    
3257
#define SHIFT 3
3258
#include "softmmu_template.h"
3259

    
3260
/* XXX: make it generic ? */
3261
static void cpu_restore_state2(void *retaddr)
3262
{
3263
    TranslationBlock *tb;
3264
    unsigned long pc;
3265

    
3266
    if (retaddr) {
3267
        /* now we have a real cpu fault */
3268
        pc = (unsigned long)retaddr;
3269
        tb = tb_find_pc(pc);
3270
        if (tb) {
3271
            /* the PC is inside the translated code. It means that we have
3272
               a virtual CPU fault */
3273
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
3274
        }
3275
    }
3276
}
3277

    
3278
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3279
                                void *retaddr)
3280
{
3281
#ifdef DEBUG_UNALIGNED
3282
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3283
           "\n", addr, env->pc);
3284
#endif
3285
    cpu_restore_state2(retaddr);
3286
    raise_exception(TT_UNALIGNED);
3287
}
3288

    
3289
/* try to fill the TLB and return an exception if error. If retaddr is
3290
   NULL, it means that the function was called in C code (i.e. not
3291
   from generated code or from helper.c) */
3292
/* XXX: fix it to restore all registers */
3293
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3294
{
3295
    int ret;
3296
    CPUState *saved_env;
3297

    
3298
    /* XXX: hack to restore env in all cases, even if not called from
3299
       generated code */
3300
    saved_env = env;
3301
    env = cpu_single_env;
3302

    
3303
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3304
    if (ret) {
3305
        cpu_restore_state2(retaddr);
3306
        cpu_loop_exit();
3307
    }
3308
    env = saved_env;
3309
}
3310

    
3311
#endif
3312

    
3313
#ifndef TARGET_SPARC64
3314
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3315
                          int is_asi, int size)
3316
{
3317
    CPUState *saved_env;
3318

    
3319
    /* XXX: hack to restore env in all cases, even if not called from
3320
       generated code */
3321
    saved_env = env;
3322
    env = cpu_single_env;
3323
#ifdef DEBUG_UNASSIGNED
3324
    if (is_asi)
3325
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3326
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3327
               is_exec ? "exec" : is_write ? "write" : "read", size,
3328
               size == 1 ? "" : "s", addr, is_asi, env->pc);
3329
    else
3330
        printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
3331
               " from " TARGET_FMT_lx "\n",
3332
               is_exec ? "exec" : is_write ? "write" : "read", size,
3333
               size == 1 ? "" : "s", addr, env->pc);
3334
#endif
3335
    if (env->mmuregs[3]) /* Fault status register */
3336
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3337
    if (is_asi)
3338
        env->mmuregs[3] |= 1 << 16;
3339
    if (env->psrs)
3340
        env->mmuregs[3] |= 1 << 5;
3341
    if (is_exec)
3342
        env->mmuregs[3] |= 1 << 6;
3343
    if (is_write)
3344
        env->mmuregs[3] |= 1 << 7;
3345
    env->mmuregs[3] |= (5 << 2) | 2;
3346
    env->mmuregs[4] = addr; /* Fault address register */
3347
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3348
        if (is_exec)
3349
            raise_exception(TT_CODE_ACCESS);
3350
        else
3351
            raise_exception(TT_DATA_ACCESS);
3352
    }
3353
    env = saved_env;
3354
}
3355
#else
3356
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3357
                          int is_asi, int size)
3358
{
3359
#ifdef DEBUG_UNASSIGNED
3360
    CPUState *saved_env;
3361

    
3362
    /* XXX: hack to restore env in all cases, even if not called from
3363
       generated code */
3364
    saved_env = env;
3365
    env = cpu_single_env;
3366
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3367
           "\n", addr, env->pc);
3368
    env = saved_env;
3369
#endif
3370
    if (is_exec)
3371
        raise_exception(TT_CODE_ACCESS);
3372
    else
3373
        raise_exception(TT_DATA_ACCESS);
3374
}
3375
#endif
3376

    
3377
#ifdef TARGET_SPARC64
3378
void helper_tick_set_count(void *opaque, uint64_t count)
3379
{
3380
#if !defined(CONFIG_USER_ONLY)
3381
    cpu_tick_set_count(opaque, count);
3382
#endif
3383
}
3384

    
3385
uint64_t helper_tick_get_count(void *opaque)
3386
{
3387
#if !defined(CONFIG_USER_ONLY)
3388
    return cpu_tick_get_count(opaque);
3389
#else
3390
    return 0;
3391
#endif
3392
}
3393

    
3394
void helper_tick_set_limit(void *opaque, uint64_t limit)
3395
{
3396
#if !defined(CONFIG_USER_ONLY)
3397
    cpu_tick_set_limit(opaque, limit);
3398
#endif
3399
}
3400
#endif