Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 1d01299d

History | View | Annotate | Download (85.7 kB)

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

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

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

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

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

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

    
43
static inline void address_mask(CPUState *env1, target_ulong *addr)
44
{
45
#ifdef TARGET_SPARC64
46
    if (AM_CHECK(env1))
47
        *addr &= 0xffffffffULL;
48
#endif
49
}
50

    
51
void raise_exception(int tt)
52
{
53
    env->exception_index = tt;
54
    cpu_loop_exit();
55
}
56

    
57
void helper_trap(target_ulong nb_trap)
58
{
59
    env->exception_index = TT_TRAP + (nb_trap & 0x7f);
60
    cpu_loop_exit();
61
}
62

    
63
void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
64
{
65
    if (do_trap) {
66
        env->exception_index = TT_TRAP + (nb_trap & 0x7f);
67
        cpu_loop_exit();
68
    }
69
}
70

    
71
static inline void set_cwp(int new_cwp)
72
{
73
    cpu_set_cwp(env, new_cwp);
74
}
75

    
76
void helper_check_align(target_ulong addr, uint32_t align)
77
{
78
    if (addr & align) {
79
#ifdef DEBUG_UNALIGNED
80
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
81
           "\n", addr, env->pc);
82
#endif
83
        raise_exception(TT_UNALIGNED);
84
    }
85
}
86

    
87
#define F_HELPER(name, p) void helper_f##name##p(void)
88

    
89
#define F_BINOP(name)                                           \
90
    float32 helper_f ## name ## s (float32 src1, float32 src2)  \
91
    {                                                           \
92
        return float32_ ## name (src1, src2, &env->fp_status);  \
93
    }                                                           \
94
    F_HELPER(name, d)                                           \
95
    {                                                           \
96
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
97
    }                                                           \
98
    F_HELPER(name, q)                                           \
99
    {                                                           \
100
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
101
    }
102

    
103
F_BINOP(add);
104
F_BINOP(sub);
105
F_BINOP(mul);
106
F_BINOP(div);
107
#undef F_BINOP
108

    
109
void helper_fsmuld(void)
110
{
111
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
112
                      float32_to_float64(FT1, &env->fp_status),
113
                      &env->fp_status);
114
}
115

    
116
void helper_fdmulq(void)
117
{
118
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
119
                       float64_to_float128(DT1, &env->fp_status),
120
                       &env->fp_status);
121
}
122

    
123
float32 helper_fnegs(float32 src)
124
{
125
    return float32_chs(src);
126
}
127

    
128
#ifdef TARGET_SPARC64
129
F_HELPER(neg, d)
130
{
131
    DT0 = float64_chs(DT1);
132
}
133

    
134
F_HELPER(neg, q)
135
{
136
    QT0 = float128_chs(QT1);
137
}
138
#endif
139

    
140
/* Integer to float conversion.  */
141
float32 helper_fitos(int32_t src)
142
{
143
    return int32_to_float32(src, &env->fp_status);
144
}
145

    
146
F_HELPER(ito, d)
147
{
148
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
149
}
150

    
151
F_HELPER(ito, q)
152
{
153
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
154
}
155

    
156
#ifdef TARGET_SPARC64
157
F_HELPER(xto, s)
158
{
159
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
160
}
161

    
162
F_HELPER(xto, d)
163
{
164
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
165
}
166

    
167
F_HELPER(xto, q)
168
{
169
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
170
}
171
#endif
172
#undef F_HELPER
173

    
174
/* floating point conversion */
175
void helper_fdtos(void)
176
{
177
    FT0 = float64_to_float32(DT1, &env->fp_status);
178
}
179

    
180
void helper_fstod(void)
181
{
182
    DT0 = float32_to_float64(FT1, &env->fp_status);
183
}
184

    
185
void helper_fqtos(void)
186
{
187
    FT0 = float128_to_float32(QT1, &env->fp_status);
188
}
189

    
190
void helper_fstoq(void)
191
{
192
    QT0 = float32_to_float128(FT1, &env->fp_status);
193
}
194

    
195
void helper_fqtod(void)
196
{
197
    DT0 = float128_to_float64(QT1, &env->fp_status);
198
}
199

    
200
void helper_fdtoq(void)
201
{
202
    QT0 = float64_to_float128(DT1, &env->fp_status);
203
}
204

    
205
/* Float to integer conversion.  */
206
int32_t helper_fstoi(float32 src)
207
{
208
    return float32_to_int32_round_to_zero(src, &env->fp_status);
209
}
210

    
211
void helper_fdtoi(void)
212
{
213
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
214
}
215

    
216
void helper_fqtoi(void)
217
{
218
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
219
}
220

    
221
#ifdef TARGET_SPARC64
222
void helper_fstox(void)
223
{
224
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
225
}
226

    
227
void helper_fdtox(void)
228
{
229
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
230
}
231

    
232
void helper_fqtox(void)
233
{
234
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
235
}
236

    
237
void helper_faligndata(void)
238
{
239
    uint64_t tmp;
240

    
241
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
242
    /* on many architectures a shift of 64 does nothing */
243
    if ((env->gsr & 7) != 0) {
244
        tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
245
    }
246
    *((uint64_t *)&DT0) = tmp;
247
}
248

    
249
void helper_fnot(void)
250
{
251
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
252
}
253

    
254
void helper_fnor(void)
255
{
256
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
257
}
258

    
259
void helper_for(void)
260
{
261
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
262
}
263

    
264
void helper_fxor(void)
265
{
266
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
267
}
268

    
269
void helper_fand(void)
270
{
271
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
272
}
273

    
274
void helper_fornot(void)
275
{
276
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
277
}
278

    
279
void helper_fandnot(void)
280
{
281
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
282
}
283

    
284
void helper_fnand(void)
285
{
286
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
287
}
288

    
289
void helper_fxnor(void)
290
{
291
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
292
}
293

    
294
#ifdef WORDS_BIGENDIAN
295
#define VIS_B64(n) b[7 - (n)]
296
#define VIS_W64(n) w[3 - (n)]
297
#define VIS_SW64(n) sw[3 - (n)]
298
#define VIS_L64(n) l[1 - (n)]
299
#define VIS_B32(n) b[3 - (n)]
300
#define VIS_W32(n) w[1 - (n)]
301
#else
302
#define VIS_B64(n) b[n]
303
#define VIS_W64(n) w[n]
304
#define VIS_SW64(n) sw[n]
305
#define VIS_L64(n) l[n]
306
#define VIS_B32(n) b[n]
307
#define VIS_W32(n) w[n]
308
#endif
309

    
310
typedef union {
311
    uint8_t b[8];
312
    uint16_t w[4];
313
    int16_t sw[4];
314
    uint32_t l[2];
315
    float64 d;
316
} vis64;
317

    
318
typedef union {
319
    uint8_t b[4];
320
    uint16_t w[2];
321
    uint32_t l;
322
    float32 f;
323
} vis32;
324

    
325
void helper_fpmerge(void)
326
{
327
    vis64 s, d;
328

    
329
    s.d = DT0;
330
    d.d = DT1;
331

    
332
    // Reverse calculation order to handle overlap
333
    d.VIS_B64(7) = s.VIS_B64(3);
334
    d.VIS_B64(6) = d.VIS_B64(3);
335
    d.VIS_B64(5) = s.VIS_B64(2);
336
    d.VIS_B64(4) = d.VIS_B64(2);
337
    d.VIS_B64(3) = s.VIS_B64(1);
338
    d.VIS_B64(2) = d.VIS_B64(1);
339
    d.VIS_B64(1) = s.VIS_B64(0);
340
    //d.VIS_B64(0) = d.VIS_B64(0);
341

    
342
    DT0 = d.d;
343
}
344

    
345
void helper_fmul8x16(void)
346
{
347
    vis64 s, d;
348
    uint32_t tmp;
349

    
350
    s.d = DT0;
351
    d.d = DT1;
352

    
353
#define PMUL(r)                                                 \
354
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
355
    if ((tmp & 0xff) > 0x7f)                                    \
356
        tmp += 0x100;                                           \
357
    d.VIS_W64(r) = tmp >> 8;
358

    
359
    PMUL(0);
360
    PMUL(1);
361
    PMUL(2);
362
    PMUL(3);
363
#undef PMUL
364

    
365
    DT0 = d.d;
366
}
367

    
368
void helper_fmul8x16al(void)
369
{
370
    vis64 s, d;
371
    uint32_t tmp;
372

    
373
    s.d = DT0;
374
    d.d = DT1;
375

    
376
#define PMUL(r)                                                 \
377
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
378
    if ((tmp & 0xff) > 0x7f)                                    \
379
        tmp += 0x100;                                           \
380
    d.VIS_W64(r) = tmp >> 8;
381

    
382
    PMUL(0);
383
    PMUL(1);
384
    PMUL(2);
385
    PMUL(3);
386
#undef PMUL
387

    
388
    DT0 = d.d;
389
}
390

    
391
void helper_fmul8x16au(void)
392
{
393
    vis64 s, d;
394
    uint32_t tmp;
395

    
396
    s.d = DT0;
397
    d.d = DT1;
398

    
399
#define PMUL(r)                                                 \
400
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
401
    if ((tmp & 0xff) > 0x7f)                                    \
402
        tmp += 0x100;                                           \
403
    d.VIS_W64(r) = tmp >> 8;
404

    
405
    PMUL(0);
406
    PMUL(1);
407
    PMUL(2);
408
    PMUL(3);
409
#undef PMUL
410

    
411
    DT0 = d.d;
412
}
413

    
414
void helper_fmul8sux16(void)
415
{
416
    vis64 s, d;
417
    uint32_t tmp;
418

    
419
    s.d = DT0;
420
    d.d = DT1;
421

    
422
#define PMUL(r)                                                         \
423
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
424
    if ((tmp & 0xff) > 0x7f)                                            \
425
        tmp += 0x100;                                                   \
426
    d.VIS_W64(r) = tmp >> 8;
427

    
428
    PMUL(0);
429
    PMUL(1);
430
    PMUL(2);
431
    PMUL(3);
432
#undef PMUL
433

    
434
    DT0 = d.d;
435
}
436

    
437
void helper_fmul8ulx16(void)
438
{
439
    vis64 s, d;
440
    uint32_t tmp;
441

    
442
    s.d = DT0;
443
    d.d = DT1;
444

    
445
#define PMUL(r)                                                         \
446
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
447
    if ((tmp & 0xff) > 0x7f)                                            \
448
        tmp += 0x100;                                                   \
449
    d.VIS_W64(r) = tmp >> 8;
450

    
451
    PMUL(0);
452
    PMUL(1);
453
    PMUL(2);
454
    PMUL(3);
455
#undef PMUL
456

    
457
    DT0 = d.d;
458
}
459

    
460
void helper_fmuld8sux16(void)
461
{
462
    vis64 s, d;
463
    uint32_t tmp;
464

    
465
    s.d = DT0;
466
    d.d = DT1;
467

    
468
#define PMUL(r)                                                         \
469
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
470
    if ((tmp & 0xff) > 0x7f)                                            \
471
        tmp += 0x100;                                                   \
472
    d.VIS_L64(r) = tmp;
473

    
474
    // Reverse calculation order to handle overlap
475
    PMUL(1);
476
    PMUL(0);
477
#undef PMUL
478

    
479
    DT0 = d.d;
480
}
481

    
482
void helper_fmuld8ulx16(void)
483
{
484
    vis64 s, d;
485
    uint32_t tmp;
486

    
487
    s.d = DT0;
488
    d.d = DT1;
489

    
490
#define PMUL(r)                                                         \
491
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
492
    if ((tmp & 0xff) > 0x7f)                                            \
493
        tmp += 0x100;                                                   \
494
    d.VIS_L64(r) = tmp;
495

    
496
    // Reverse calculation order to handle overlap
497
    PMUL(1);
498
    PMUL(0);
499
#undef PMUL
500

    
501
    DT0 = d.d;
502
}
503

    
504
void helper_fexpand(void)
505
{
506
    vis32 s;
507
    vis64 d;
508

    
509
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
510
    d.d = DT1;
511
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
512
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
513
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
514
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
515

    
516
    DT0 = d.d;
517
}
518

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

    
573
#define FADD(a, b) ((a) + (b))
574
#define FSUB(a, b) ((a) - (b))
575
VIS_HELPER(helper_fpadd, FADD)
576
VIS_HELPER(helper_fpsub, FSUB)
577

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

    
607
#define FCMPGT(a, b) ((a) > (b))
608
#define FCMPEQ(a, b) ((a) == (b))
609
#define FCMPLE(a, b) ((a) <= (b))
610
#define FCMPNE(a, b) ((a) != (b))
611

    
612
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
613
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
614
VIS_CMPHELPER(helper_fcmple, FCMPLE)
615
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
616
#endif
617

    
618
void helper_check_ieee_exceptions(void)
619
{
620
    target_ulong status;
621

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

    
636
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
637
            /* Unmasked exception, generate a trap */
638
            env->fsr |= FSR_FTT_IEEE_EXCP;
639
            raise_exception(TT_FP_EXCP);
640
        } else {
641
            /* Accumulate exceptions */
642
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
643
        }
644
    }
645
}
646

    
647
void helper_clear_float_exceptions(void)
648
{
649
    set_float_exception_flags(0, &env->fp_status);
650
}
651

    
652
float32 helper_fabss(float32 src)
653
{
654
    return float32_abs(src);
655
}
656

    
657
#ifdef TARGET_SPARC64
658
void helper_fabsd(void)
659
{
660
    DT0 = float64_abs(DT1);
661
}
662

    
663
void helper_fabsq(void)
664
{
665
    QT0 = float128_abs(QT1);
666
}
667
#endif
668

    
669
float32 helper_fsqrts(float32 src)
670
{
671
    return float32_sqrt(src, &env->fp_status);
672
}
673

    
674
void helper_fsqrtd(void)
675
{
676
    DT0 = float64_sqrt(DT1, &env->fp_status);
677
}
678

    
679
void helper_fsqrtq(void)
680
{
681
    QT0 = float128_sqrt(QT1, &env->fp_status);
682
}
683

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

    
745
GEN_FCMPS(fcmps, float32, 0, 0);
746
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
747

    
748
GEN_FCMPS(fcmpes, float32, 0, 1);
749
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
750

    
751
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
752
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
753

    
754
#ifdef TARGET_SPARC64
755
GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
756
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
757
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
758

    
759
GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
760
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
761
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
762

    
763
GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
764
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
765
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
766

    
767
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
768
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
769
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
770

    
771
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
772
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
773
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
774

    
775
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
776
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
777
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
778
#endif
779
#undef GEN_FCMPS
780

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

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

    
824
#ifndef TARGET_SPARC64
825
#ifndef CONFIG_USER_ONLY
826
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
827
{
828
    uint64_t ret = 0;
829
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
830
    uint32_t last_addr = addr;
831
#endif
832

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

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

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

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

    
1145
            mmulev = (addr >> 8) & 15;
1146
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1147
            switch (mmulev) {
1148
            case 0: // flush page
1149
                tlb_flush_page(env, addr & 0xfffff000);
1150
                break;
1151
            case 1: // flush segment (256k)
1152
            case 2: // flush region (16M)
1153
            case 3: // flush context (4G)
1154
            case 4: // flush entire
1155
                tlb_flush(env, 1);
1156
                break;
1157
            default:
1158
                break;
1159
            }
1160
#ifdef DEBUG_MMU
1161
            dump_mmu(env);
1162
#endif
1163
        }
1164
        break;
1165
    case 4: /* write MMU regs */
1166
        {
1167
            int reg = (addr >> 8) & 0x1f;
1168
            uint32_t oldreg;
1169

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

    
1273
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1274
                temp = ldl_kernel(src);
1275
                stl_kernel(dst, temp);
1276
            }
1277
        }
1278
        break;
1279
    case 0x1f: /* Block fill, stda access */
1280
        {
1281
            // addr = dst
1282
            // fill 32 bytes with val
1283
            unsigned int i;
1284
            uint32_t dst = addr & 7;
1285

    
1286
            for (i = 0; i < 32; i += 8, dst += 8)
1287
                stq_kernel(dst, val);
1288
        }
1289
        break;
1290
    case 0x20: /* MMU passthrough */
1291
        {
1292
            switch(size) {
1293
            case 1:
1294
                stb_phys(addr, val);
1295
                break;
1296
            case 2:
1297
                stw_phys(addr, val);
1298
                break;
1299
            case 4:
1300
            default:
1301
                stl_phys(addr, val);
1302
                break;
1303
            case 8:
1304
                stq_phys(addr, val);
1305
                break;
1306
            }
1307
        }
1308
        break;
1309
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1310
        {
1311
            switch(size) {
1312
            case 1:
1313
                stb_phys((target_phys_addr_t)addr
1314
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1315
                break;
1316
            case 2:
1317
                stw_phys((target_phys_addr_t)addr
1318
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1319
                break;
1320
            case 4:
1321
            default:
1322
                stl_phys((target_phys_addr_t)addr
1323
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1324
                break;
1325
            case 8:
1326
                stq_phys((target_phys_addr_t)addr
1327
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1328
                break;
1329
            }
1330
        }
1331
        break;
1332
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1333
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1334
               // Turbosparc snoop RAM
1335
    case 0x32: // store buffer control or Turbosparc page table
1336
               // descriptor diagnostic
1337
    case 0x36: /* I-cache flash clear */
1338
    case 0x37: /* D-cache flash clear */
1339
    case 0x38: /* breakpoint diagnostics */
1340
    case 0x4c: /* breakpoint action */
1341
        break;
1342
    case 8: /* User code access, XXX */
1343
    case 9: /* Supervisor code access, XXX */
1344
    default:
1345
        do_unassigned_access(addr, 1, 0, asi);
1346
        break;
1347
    }
1348
#ifdef DEBUG_ASI
1349
    dump_asi("write", addr, asi, size, val);
1350
#endif
1351
}
1352

    
1353
#endif /* CONFIG_USER_ONLY */
1354
#else /* TARGET_SPARC64 */
1355

    
1356
#ifdef CONFIG_USER_ONLY
1357
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1358
{
1359
    uint64_t ret = 0;
1360
#if defined(DEBUG_ASI)
1361
    target_ulong last_addr = addr;
1362
#endif
1363

    
1364
    if (asi < 0x80)
1365
        raise_exception(TT_PRIV_ACT);
1366

    
1367
    helper_check_align(addr, size - 1);
1368
    address_mask(env, &addr);
1369

    
1370
    switch (asi) {
1371
    case 0x82: // Primary no-fault
1372
    case 0x8a: // Primary no-fault LE
1373
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1374
#ifdef DEBUG_ASI
1375
            dump_asi("read ", last_addr, asi, size, ret);
1376
#endif
1377
            return 0;
1378
        }
1379
        // Fall through
1380
    case 0x80: // Primary
1381
    case 0x88: // Primary LE
1382
        {
1383
            switch(size) {
1384
            case 1:
1385
                ret = ldub_raw(addr);
1386
                break;
1387
            case 2:
1388
                ret = lduw_raw(addr);
1389
                break;
1390
            case 4:
1391
                ret = ldl_raw(addr);
1392
                break;
1393
            default:
1394
            case 8:
1395
                ret = ldq_raw(addr);
1396
                break;
1397
            }
1398
        }
1399
        break;
1400
    case 0x83: // Secondary no-fault
1401
    case 0x8b: // Secondary no-fault LE
1402
        if (page_check_range(addr, size, PAGE_READ) == -1) {
1403
#ifdef DEBUG_ASI
1404
            dump_asi("read ", last_addr, asi, size, ret);
1405
#endif
1406
            return 0;
1407
        }
1408
        // Fall through
1409
    case 0x81: // Secondary
1410
    case 0x89: // Secondary LE
1411
        // XXX
1412
        break;
1413
    default:
1414
        break;
1415
    }
1416

    
1417
    /* Convert from little endian */
1418
    switch (asi) {
1419
    case 0x88: // Primary LE
1420
    case 0x89: // Secondary LE
1421
    case 0x8a: // Primary no-fault LE
1422
    case 0x8b: // Secondary no-fault LE
1423
        switch(size) {
1424
        case 2:
1425
            ret = bswap16(ret);
1426
            break;
1427
        case 4:
1428
            ret = bswap32(ret);
1429
            break;
1430
        case 8:
1431
            ret = bswap64(ret);
1432
            break;
1433
        default:
1434
            break;
1435
        }
1436
    default:
1437
        break;
1438
    }
1439

    
1440
    /* Convert to signed number */
1441
    if (sign) {
1442
        switch(size) {
1443
        case 1:
1444
            ret = (int8_t) ret;
1445
            break;
1446
        case 2:
1447
            ret = (int16_t) ret;
1448
            break;
1449
        case 4:
1450
            ret = (int32_t) ret;
1451
            break;
1452
        default:
1453
            break;
1454
        }
1455
    }
1456
#ifdef DEBUG_ASI
1457
    dump_asi("read ", last_addr, asi, size, ret);
1458
#endif
1459
    return ret;
1460
}
1461

    
1462
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1463
{
1464
#ifdef DEBUG_ASI
1465
    dump_asi("write", addr, asi, size, val);
1466
#endif
1467
    if (asi < 0x80)
1468
        raise_exception(TT_PRIV_ACT);
1469

    
1470
    helper_check_align(addr, size - 1);
1471
    address_mask(env, &addr);
1472

    
1473
    /* Convert to little endian */
1474
    switch (asi) {
1475
    case 0x88: // Primary LE
1476
    case 0x89: // Secondary LE
1477
        switch(size) {
1478
        case 2:
1479
            addr = bswap16(addr);
1480
            break;
1481
        case 4:
1482
            addr = bswap32(addr);
1483
            break;
1484
        case 8:
1485
            addr = bswap64(addr);
1486
            break;
1487
        default:
1488
            break;
1489
        }
1490
    default:
1491
        break;
1492
    }
1493

    
1494
    switch(asi) {
1495
    case 0x80: // Primary
1496
    case 0x88: // Primary LE
1497
        {
1498
            switch(size) {
1499
            case 1:
1500
                stb_raw(addr, val);
1501
                break;
1502
            case 2:
1503
                stw_raw(addr, val);
1504
                break;
1505
            case 4:
1506
                stl_raw(addr, val);
1507
                break;
1508
            case 8:
1509
            default:
1510
                stq_raw(addr, val);
1511
                break;
1512
            }
1513
        }
1514
        break;
1515
    case 0x81: // Secondary
1516
    case 0x89: // Secondary LE
1517
        // XXX
1518
        return;
1519

    
1520
    case 0x82: // Primary no-fault, RO
1521
    case 0x83: // Secondary no-fault, RO
1522
    case 0x8a: // Primary no-fault LE, RO
1523
    case 0x8b: // Secondary no-fault LE, RO
1524
    default:
1525
        do_unassigned_access(addr, 1, 0, 1);
1526
        return;
1527
    }
1528
}
1529

    
1530
#else /* CONFIG_USER_ONLY */
1531

    
1532
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1533
{
1534
    uint64_t ret = 0;
1535
#if defined(DEBUG_ASI)
1536
    target_ulong last_addr = addr;
1537
#endif
1538

    
1539
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1540
        || ((env->def->features & CPU_FEATURE_HYPV)
1541
            && asi >= 0x30 && asi < 0x80
1542
            && !(env->hpstate & HS_PRIV)))
1543
        raise_exception(TT_PRIV_ACT);
1544

    
1545
    helper_check_align(addr, size - 1);
1546
    switch (asi) {
1547
    case 0x82: // Primary no-fault
1548
    case 0x8a: // Primary no-fault LE
1549
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1550
#ifdef DEBUG_ASI
1551
            dump_asi("read ", last_addr, asi, size, ret);
1552
#endif
1553
            return 0;
1554
        }
1555
        // Fall through
1556
    case 0x10: // As if user primary
1557
    case 0x18: // As if user primary LE
1558
    case 0x80: // Primary
1559
    case 0x88: // Primary LE
1560
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1561
            if ((env->def->features & CPU_FEATURE_HYPV)
1562
                && env->hpstate & HS_PRIV) {
1563
                switch(size) {
1564
                case 1:
1565
                    ret = ldub_hypv(addr);
1566
                    break;
1567
                case 2:
1568
                    ret = lduw_hypv(addr);
1569
                    break;
1570
                case 4:
1571
                    ret = ldl_hypv(addr);
1572
                    break;
1573
                default:
1574
                case 8:
1575
                    ret = ldq_hypv(addr);
1576
                    break;
1577
                }
1578
            } else {
1579
                switch(size) {
1580
                case 1:
1581
                    ret = ldub_kernel(addr);
1582
                    break;
1583
                case 2:
1584
                    ret = lduw_kernel(addr);
1585
                    break;
1586
                case 4:
1587
                    ret = ldl_kernel(addr);
1588
                    break;
1589
                default:
1590
                case 8:
1591
                    ret = ldq_kernel(addr);
1592
                    break;
1593
                }
1594
            }
1595
        } else {
1596
            switch(size) {
1597
            case 1:
1598
                ret = ldub_user(addr);
1599
                break;
1600
            case 2:
1601
                ret = lduw_user(addr);
1602
                break;
1603
            case 4:
1604
                ret = ldl_user(addr);
1605
                break;
1606
            default:
1607
            case 8:
1608
                ret = ldq_user(addr);
1609
                break;
1610
            }
1611
        }
1612
        break;
1613
    case 0x14: // Bypass
1614
    case 0x15: // Bypass, non-cacheable
1615
    case 0x1c: // Bypass LE
1616
    case 0x1d: // Bypass, non-cacheable LE
1617
        {
1618
            switch(size) {
1619
            case 1:
1620
                ret = ldub_phys(addr);
1621
                break;
1622
            case 2:
1623
                ret = lduw_phys(addr);
1624
                break;
1625
            case 4:
1626
                ret = ldl_phys(addr);
1627
                break;
1628
            default:
1629
            case 8:
1630
                ret = ldq_phys(addr);
1631
                break;
1632
            }
1633
            break;
1634
        }
1635
    case 0x24: // Nucleus quad LDD 128 bit atomic
1636
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1637
        //  Only ldda allowed
1638
        raise_exception(TT_ILL_INSN);
1639
        return 0;
1640
    case 0x83: // Secondary no-fault
1641
    case 0x8b: // Secondary no-fault LE
1642
        if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
1643
#ifdef DEBUG_ASI
1644
            dump_asi("read ", last_addr, asi, size, ret);
1645
#endif
1646
            return 0;
1647
        }
1648
        // Fall through
1649
    case 0x04: // Nucleus
1650
    case 0x0c: // Nucleus Little Endian (LE)
1651
    case 0x11: // As if user secondary
1652
    case 0x19: // As if user secondary LE
1653
    case 0x4a: // UPA config
1654
    case 0x81: // Secondary
1655
    case 0x89: // Secondary LE
1656
        // XXX
1657
        break;
1658
    case 0x45: // LSU
1659
        ret = env->lsu;
1660
        break;
1661
    case 0x50: // I-MMU regs
1662
        {
1663
            int reg = (addr >> 3) & 0xf;
1664

    
1665
            ret = env->immuregs[reg];
1666
            break;
1667
        }
1668
    case 0x51: // I-MMU 8k TSB pointer
1669
    case 0x52: // I-MMU 64k TSB pointer
1670
        // XXX
1671
        break;
1672
    case 0x55: // I-MMU data access
1673
        {
1674
            int reg = (addr >> 3) & 0x3f;
1675

    
1676
            ret = env->itlb_tte[reg];
1677
            break;
1678
        }
1679
    case 0x56: // I-MMU tag read
1680
        {
1681
            int reg = (addr >> 3) & 0x3f;
1682

    
1683
            ret = env->itlb_tag[reg];
1684
            break;
1685
        }
1686
    case 0x58: // D-MMU regs
1687
        {
1688
            int reg = (addr >> 3) & 0xf;
1689

    
1690
            ret = env->dmmuregs[reg];
1691
            break;
1692
        }
1693
    case 0x5d: // D-MMU data access
1694
        {
1695
            int reg = (addr >> 3) & 0x3f;
1696

    
1697
            ret = env->dtlb_tte[reg];
1698
            break;
1699
        }
1700
    case 0x5e: // D-MMU tag read
1701
        {
1702
            int reg = (addr >> 3) & 0x3f;
1703

    
1704
            ret = env->dtlb_tag[reg];
1705
            break;
1706
        }
1707
    case 0x46: // D-cache data
1708
    case 0x47: // D-cache tag access
1709
    case 0x4b: // E-cache error enable
1710
    case 0x4c: // E-cache asynchronous fault status
1711
    case 0x4d: // E-cache asynchronous fault address
1712
    case 0x4e: // E-cache tag data
1713
    case 0x66: // I-cache instruction access
1714
    case 0x67: // I-cache tag access
1715
    case 0x6e: // I-cache predecode
1716
    case 0x6f: // I-cache LRU etc.
1717
    case 0x76: // E-cache tag
1718
    case 0x7e: // E-cache tag
1719
        break;
1720
    case 0x59: // D-MMU 8k TSB pointer
1721
    case 0x5a: // D-MMU 64k TSB pointer
1722
    case 0x5b: // D-MMU data pointer
1723
    case 0x48: // Interrupt dispatch, RO
1724
    case 0x49: // Interrupt data receive
1725
    case 0x7f: // Incoming interrupt vector, RO
1726
        // XXX
1727
        break;
1728
    case 0x54: // I-MMU data in, WO
1729
    case 0x57: // I-MMU demap, WO
1730
    case 0x5c: // D-MMU data in, WO
1731
    case 0x5f: // D-MMU demap, WO
1732
    case 0x77: // Interrupt vector, WO
1733
    default:
1734
        do_unassigned_access(addr, 0, 0, 1);
1735
        ret = 0;
1736
        break;
1737
    }
1738

    
1739
    /* Convert from little endian */
1740
    switch (asi) {
1741
    case 0x0c: // Nucleus Little Endian (LE)
1742
    case 0x18: // As if user primary LE
1743
    case 0x19: // As if user secondary LE
1744
    case 0x1c: // Bypass LE
1745
    case 0x1d: // Bypass, non-cacheable LE
1746
    case 0x88: // Primary LE
1747
    case 0x89: // Secondary LE
1748
    case 0x8a: // Primary no-fault LE
1749
    case 0x8b: // Secondary no-fault LE
1750
        switch(size) {
1751
        case 2:
1752
            ret = bswap16(ret);
1753
            break;
1754
        case 4:
1755
            ret = bswap32(ret);
1756
            break;
1757
        case 8:
1758
            ret = bswap64(ret);
1759
            break;
1760
        default:
1761
            break;
1762
        }
1763
    default:
1764
        break;
1765
    }
1766

    
1767
    /* Convert to signed number */
1768
    if (sign) {
1769
        switch(size) {
1770
        case 1:
1771
            ret = (int8_t) ret;
1772
            break;
1773
        case 2:
1774
            ret = (int16_t) ret;
1775
            break;
1776
        case 4:
1777
            ret = (int32_t) ret;
1778
            break;
1779
        default:
1780
            break;
1781
        }
1782
    }
1783
#ifdef DEBUG_ASI
1784
    dump_asi("read ", last_addr, asi, size, ret);
1785
#endif
1786
    return ret;
1787
}
1788

    
1789
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1790
{
1791
#ifdef DEBUG_ASI
1792
    dump_asi("write", addr, asi, size, val);
1793
#endif
1794
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1795
        || ((env->def->features & CPU_FEATURE_HYPV)
1796
            && asi >= 0x30 && asi < 0x80
1797
            && !(env->hpstate & HS_PRIV)))
1798
        raise_exception(TT_PRIV_ACT);
1799

    
1800
    helper_check_align(addr, size - 1);
1801
    /* Convert to little endian */
1802
    switch (asi) {
1803
    case 0x0c: // Nucleus Little Endian (LE)
1804
    case 0x18: // As if user primary LE
1805
    case 0x19: // As if user secondary LE
1806
    case 0x1c: // Bypass LE
1807
    case 0x1d: // Bypass, non-cacheable LE
1808
    case 0x88: // Primary LE
1809
    case 0x89: // Secondary LE
1810
        switch(size) {
1811
        case 2:
1812
            addr = bswap16(addr);
1813
            break;
1814
        case 4:
1815
            addr = bswap32(addr);
1816
            break;
1817
        case 8:
1818
            addr = bswap64(addr);
1819
            break;
1820
        default:
1821
            break;
1822
        }
1823
    default:
1824
        break;
1825
    }
1826

    
1827
    switch(asi) {
1828
    case 0x10: // As if user primary
1829
    case 0x18: // As if user primary LE
1830
    case 0x80: // Primary
1831
    case 0x88: // Primary LE
1832
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1833
            if ((env->def->features & CPU_FEATURE_HYPV)
1834
                && env->hpstate & HS_PRIV) {
1835
                switch(size) {
1836
                case 1:
1837
                    stb_hypv(addr, val);
1838
                    break;
1839
                case 2:
1840
                    stw_hypv(addr, val);
1841
                    break;
1842
                case 4:
1843
                    stl_hypv(addr, val);
1844
                    break;
1845
                case 8:
1846
                default:
1847
                    stq_hypv(addr, val);
1848
                    break;
1849
                }
1850
            } else {
1851
                switch(size) {
1852
                case 1:
1853
                    stb_kernel(addr, val);
1854
                    break;
1855
                case 2:
1856
                    stw_kernel(addr, val);
1857
                    break;
1858
                case 4:
1859
                    stl_kernel(addr, val);
1860
                    break;
1861
                case 8:
1862
                default:
1863
                    stq_kernel(addr, val);
1864
                    break;
1865
                }
1866
            }
1867
        } else {
1868
            switch(size) {
1869
            case 1:
1870
                stb_user(addr, val);
1871
                break;
1872
            case 2:
1873
                stw_user(addr, val);
1874
                break;
1875
            case 4:
1876
                stl_user(addr, val);
1877
                break;
1878
            case 8:
1879
            default:
1880
                stq_user(addr, val);
1881
                break;
1882
            }
1883
        }
1884
        break;
1885
    case 0x14: // Bypass
1886
    case 0x15: // Bypass, non-cacheable
1887
    case 0x1c: // Bypass LE
1888
    case 0x1d: // Bypass, non-cacheable LE
1889
        {
1890
            switch(size) {
1891
            case 1:
1892
                stb_phys(addr, val);
1893
                break;
1894
            case 2:
1895
                stw_phys(addr, val);
1896
                break;
1897
            case 4:
1898
                stl_phys(addr, val);
1899
                break;
1900
            case 8:
1901
            default:
1902
                stq_phys(addr, val);
1903
                break;
1904
            }
1905
        }
1906
        return;
1907
    case 0x24: // Nucleus quad LDD 128 bit atomic
1908
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
1909
        //  Only ldda allowed
1910
        raise_exception(TT_ILL_INSN);
1911
        return;
1912
    case 0x04: // Nucleus
1913
    case 0x0c: // Nucleus Little Endian (LE)
1914
    case 0x11: // As if user secondary
1915
    case 0x19: // As if user secondary LE
1916
    case 0x4a: // UPA config
1917
    case 0x81: // Secondary
1918
    case 0x89: // Secondary LE
1919
        // XXX
1920
        return;
1921
    case 0x45: // LSU
1922
        {
1923
            uint64_t oldreg;
1924

    
1925
            oldreg = env->lsu;
1926
            env->lsu = val & (DMMU_E | IMMU_E);
1927
            // Mappings generated during D/I MMU disabled mode are
1928
            // invalid in normal mode
1929
            if (oldreg != env->lsu) {
1930
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
1931
                            oldreg, env->lsu);
1932
#ifdef DEBUG_MMU
1933
                dump_mmu(env);
1934
#endif
1935
                tlb_flush(env, 1);
1936
            }
1937
            return;
1938
        }
1939
    case 0x50: // I-MMU regs
1940
        {
1941
            int reg = (addr >> 3) & 0xf;
1942
            uint64_t oldreg;
1943

    
1944
            oldreg = env->immuregs[reg];
1945
            switch(reg) {
1946
            case 0: // RO
1947
            case 4:
1948
                return;
1949
            case 1: // Not in I-MMU
1950
            case 2:
1951
            case 7:
1952
            case 8:
1953
                return;
1954
            case 3: // SFSR
1955
                if ((val & 1) == 0)
1956
                    val = 0; // Clear SFSR
1957
                break;
1958
            case 5: // TSB access
1959
            case 6: // Tag access
1960
            default:
1961
                break;
1962
            }
1963
            env->immuregs[reg] = val;
1964
            if (oldreg != env->immuregs[reg]) {
1965
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
1966
                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1967
            }
1968
#ifdef DEBUG_MMU
1969
            dump_mmu(env);
1970
#endif
1971
            return;
1972
        }
1973
    case 0x54: // I-MMU data in
1974
        {
1975
            unsigned int i;
1976

    
1977
            // Try finding an invalid entry
1978
            for (i = 0; i < 64; i++) {
1979
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1980
                    env->itlb_tag[i] = env->immuregs[6];
1981
                    env->itlb_tte[i] = val;
1982
                    return;
1983
                }
1984
            }
1985
            // Try finding an unlocked entry
1986
            for (i = 0; i < 64; i++) {
1987
                if ((env->itlb_tte[i] & 0x40) == 0) {
1988
                    env->itlb_tag[i] = env->immuregs[6];
1989
                    env->itlb_tte[i] = val;
1990
                    return;
1991
                }
1992
            }
1993
            // error state?
1994
            return;
1995
        }
1996
    case 0x55: // I-MMU data access
1997
        {
1998
            unsigned int i = (addr >> 3) & 0x3f;
1999

    
2000
            env->itlb_tag[i] = env->immuregs[6];
2001
            env->itlb_tte[i] = val;
2002
            return;
2003
        }
2004
    case 0x57: // I-MMU demap
2005
        // XXX
2006
        return;
2007
    case 0x58: // D-MMU regs
2008
        {
2009
            int reg = (addr >> 3) & 0xf;
2010
            uint64_t oldreg;
2011

    
2012
            oldreg = env->dmmuregs[reg];
2013
            switch(reg) {
2014
            case 0: // RO
2015
            case 4:
2016
                return;
2017
            case 3: // SFSR
2018
                if ((val & 1) == 0) {
2019
                    val = 0; // Clear SFSR, Fault address
2020
                    env->dmmuregs[4] = 0;
2021
                }
2022
                env->dmmuregs[reg] = val;
2023
                break;
2024
            case 1: // Primary context
2025
            case 2: // Secondary context
2026
            case 5: // TSB access
2027
            case 6: // Tag access
2028
            case 7: // Virtual Watchpoint
2029
            case 8: // Physical Watchpoint
2030
            default:
2031
                break;
2032
            }
2033
            env->dmmuregs[reg] = val;
2034
            if (oldreg != env->dmmuregs[reg]) {
2035
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
2036
                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
2037
            }
2038
#ifdef DEBUG_MMU
2039
            dump_mmu(env);
2040
#endif
2041
            return;
2042
        }
2043
    case 0x5c: // D-MMU data in
2044
        {
2045
            unsigned int i;
2046

    
2047
            // Try finding an invalid entry
2048
            for (i = 0; i < 64; i++) {
2049
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
2050
                    env->dtlb_tag[i] = env->dmmuregs[6];
2051
                    env->dtlb_tte[i] = val;
2052
                    return;
2053
                }
2054
            }
2055
            // Try finding an unlocked entry
2056
            for (i = 0; i < 64; i++) {
2057
                if ((env->dtlb_tte[i] & 0x40) == 0) {
2058
                    env->dtlb_tag[i] = env->dmmuregs[6];
2059
                    env->dtlb_tte[i] = val;
2060
                    return;
2061
                }
2062
            }
2063
            // error state?
2064
            return;
2065
        }
2066
    case 0x5d: // D-MMU data access
2067
        {
2068
            unsigned int i = (addr >> 3) & 0x3f;
2069

    
2070
            env->dtlb_tag[i] = env->dmmuregs[6];
2071
            env->dtlb_tte[i] = val;
2072
            return;
2073
        }
2074
    case 0x5f: // D-MMU demap
2075
    case 0x49: // Interrupt data receive
2076
        // XXX
2077
        return;
2078
    case 0x46: // D-cache data
2079
    case 0x47: // D-cache tag access
2080
    case 0x4b: // E-cache error enable
2081
    case 0x4c: // E-cache asynchronous fault status
2082
    case 0x4d: // E-cache asynchronous fault address
2083
    case 0x4e: // E-cache tag data
2084
    case 0x66: // I-cache instruction access
2085
    case 0x67: // I-cache tag access
2086
    case 0x6e: // I-cache predecode
2087
    case 0x6f: // I-cache LRU etc.
2088
    case 0x76: // E-cache tag
2089
    case 0x7e: // E-cache tag
2090
        return;
2091
    case 0x51: // I-MMU 8k TSB pointer, RO
2092
    case 0x52: // I-MMU 64k TSB pointer, RO
2093
    case 0x56: // I-MMU tag read, RO
2094
    case 0x59: // D-MMU 8k TSB pointer, RO
2095
    case 0x5a: // D-MMU 64k TSB pointer, RO
2096
    case 0x5b: // D-MMU data pointer, RO
2097
    case 0x5e: // D-MMU tag read, RO
2098
    case 0x48: // Interrupt dispatch, RO
2099
    case 0x7f: // Incoming interrupt vector, RO
2100
    case 0x82: // Primary no-fault, RO
2101
    case 0x83: // Secondary no-fault, RO
2102
    case 0x8a: // Primary no-fault LE, RO
2103
    case 0x8b: // Secondary no-fault LE, RO
2104
    default:
2105
        do_unassigned_access(addr, 1, 0, 1);
2106
        return;
2107
    }
2108
}
2109
#endif /* CONFIG_USER_ONLY */
2110

    
2111
void helper_ldda_asi(target_ulong addr, int asi, int rd)
2112
{
2113
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
2114
        || ((env->def->features & CPU_FEATURE_HYPV)
2115
            && asi >= 0x30 && asi < 0x80
2116
            && !(env->hpstate & HS_PRIV)))
2117
        raise_exception(TT_PRIV_ACT);
2118

    
2119
    switch (asi) {
2120
    case 0x24: // Nucleus quad LDD 128 bit atomic
2121
    case 0x2c: // Nucleus quad LDD 128 bit atomic LE
2122
        helper_check_align(addr, 0xf);
2123
        if (rd == 0) {
2124
            env->gregs[1] = ldq_kernel(addr + 8);
2125
            if (asi == 0x2c)
2126
                bswap64s(&env->gregs[1]);
2127
        } else if (rd < 8) {
2128
            env->gregs[rd] = ldq_kernel(addr);
2129
            env->gregs[rd + 1] = ldq_kernel(addr + 8);
2130
            if (asi == 0x2c) {
2131
                bswap64s(&env->gregs[rd]);
2132
                bswap64s(&env->gregs[rd + 1]);
2133
            }
2134
        } else {
2135
            env->regwptr[rd] = ldq_kernel(addr);
2136
            env->regwptr[rd + 1] = ldq_kernel(addr + 8);
2137
            if (asi == 0x2c) {
2138
                bswap64s(&env->regwptr[rd]);
2139
                bswap64s(&env->regwptr[rd + 1]);
2140
            }
2141
        }
2142
        break;
2143
    default:
2144
        helper_check_align(addr, 0x3);
2145
        if (rd == 0)
2146
            env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
2147
        else if (rd < 8) {
2148
            env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
2149
            env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2150
        } else {
2151
            env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
2152
            env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
2153
        }
2154
        break;
2155
    }
2156
}
2157

    
2158
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2159
{
2160
    unsigned int i;
2161
    target_ulong val;
2162

    
2163
    helper_check_align(addr, 3);
2164
    switch (asi) {
2165
    case 0xf0: // Block load primary
2166
    case 0xf1: // Block load secondary
2167
    case 0xf8: // Block load primary LE
2168
    case 0xf9: // Block load secondary LE
2169
        if (rd & 7) {
2170
            raise_exception(TT_ILL_INSN);
2171
            return;
2172
        }
2173
        helper_check_align(addr, 0x3f);
2174
        for (i = 0; i < 16; i++) {
2175
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
2176
                                                         0);
2177
            addr += 4;
2178
        }
2179

    
2180
        return;
2181
    default:
2182
        break;
2183
    }
2184

    
2185
    val = helper_ld_asi(addr, asi, size, 0);
2186
    switch(size) {
2187
    default:
2188
    case 4:
2189
        *((uint32_t *)&env->fpr[rd]) = val;
2190
        break;
2191
    case 8:
2192
        *((int64_t *)&DT0) = val;
2193
        break;
2194
    case 16:
2195
        // XXX
2196
        break;
2197
    }
2198
}
2199

    
2200
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2201
{
2202
    unsigned int i;
2203
    target_ulong val = 0;
2204

    
2205
    helper_check_align(addr, 3);
2206
    switch (asi) {
2207
    case 0xf0: // Block store primary
2208
    case 0xf1: // Block store secondary
2209
    case 0xf8: // Block store primary LE
2210
    case 0xf9: // Block store secondary LE
2211
        if (rd & 7) {
2212
            raise_exception(TT_ILL_INSN);
2213
            return;
2214
        }
2215
        helper_check_align(addr, 0x3f);
2216
        for (i = 0; i < 16; i++) {
2217
            val = *(uint32_t *)&env->fpr[rd++];
2218
            helper_st_asi(addr, val, asi & 0x8f, 4);
2219
            addr += 4;
2220
        }
2221

    
2222
        return;
2223
    default:
2224
        break;
2225
    }
2226

    
2227
    switch(size) {
2228
    default:
2229
    case 4:
2230
        val = *((uint32_t *)&env->fpr[rd]);
2231
        break;
2232
    case 8:
2233
        val = *((int64_t *)&DT0);
2234
        break;
2235
    case 16:
2236
        // XXX
2237
        break;
2238
    }
2239
    helper_st_asi(addr, val, asi, size);
2240
}
2241

    
2242
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2243
                            target_ulong val2, uint32_t asi)
2244
{
2245
    target_ulong ret;
2246

    
2247
    val1 &= 0xffffffffUL;
2248
    ret = helper_ld_asi(addr, asi, 4, 0);
2249
    ret &= 0xffffffffUL;
2250
    if (val1 == ret)
2251
        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2252
    return ret;
2253
}
2254

    
2255
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2256
                             target_ulong val2, uint32_t asi)
2257
{
2258
    target_ulong ret;
2259

    
2260
    ret = helper_ld_asi(addr, asi, 8, 0);
2261
    if (val1 == ret)
2262
        helper_st_asi(addr, val2, asi, 8);
2263
    return ret;
2264
}
2265
#endif /* TARGET_SPARC64 */
2266

    
2267
#ifndef TARGET_SPARC64
2268
void helper_rett(void)
2269
{
2270
    unsigned int cwp;
2271

    
2272
    if (env->psret == 1)
2273
        raise_exception(TT_ILL_INSN);
2274

    
2275
    env->psret = 1;
2276
    cwp = cpu_cwp_inc(env, env->cwp + 1) ;
2277
    if (env->wim & (1 << cwp)) {
2278
        raise_exception(TT_WIN_UNF);
2279
    }
2280
    set_cwp(cwp);
2281
    env->psrs = env->psrps;
2282
}
2283
#endif
2284

    
2285
target_ulong helper_udiv(target_ulong a, target_ulong b)
2286
{
2287
    uint64_t x0;
2288
    uint32_t x1;
2289

    
2290
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2291
    x1 = b;
2292

    
2293
    if (x1 == 0) {
2294
        raise_exception(TT_DIV_ZERO);
2295
    }
2296

    
2297
    x0 = x0 / x1;
2298
    if (x0 > 0xffffffff) {
2299
        env->cc_src2 = 1;
2300
        return 0xffffffff;
2301
    } else {
2302
        env->cc_src2 = 0;
2303
        return x0;
2304
    }
2305
}
2306

    
2307
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2308
{
2309
    int64_t x0;
2310
    int32_t x1;
2311

    
2312
    x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
2313
    x1 = b;
2314

    
2315
    if (x1 == 0) {
2316
        raise_exception(TT_DIV_ZERO);
2317
    }
2318

    
2319
    x0 = x0 / x1;
2320
    if ((int32_t) x0 != x0) {
2321
        env->cc_src2 = 1;
2322
        return x0 < 0? 0x80000000: 0x7fffffff;
2323
    } else {
2324
        env->cc_src2 = 0;
2325
        return x0;
2326
    }
2327
}
2328

    
2329
uint64_t helper_pack64(target_ulong high, target_ulong low)
2330
{
2331
    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2332
}
2333

    
2334
void helper_stdf(target_ulong addr, int mem_idx)
2335
{
2336
    helper_check_align(addr, 7);
2337
#if !defined(CONFIG_USER_ONLY)
2338
    switch (mem_idx) {
2339
    case 0:
2340
        stfq_user(addr, DT0);
2341
        break;
2342
    case 1:
2343
        stfq_kernel(addr, DT0);
2344
        break;
2345
#ifdef TARGET_SPARC64
2346
    case 2:
2347
        stfq_hypv(addr, DT0);
2348
        break;
2349
#endif
2350
    default:
2351
        break;
2352
    }
2353
#else
2354
    address_mask(env, &addr);
2355
    stfq_raw(addr, DT0);
2356
#endif
2357
}
2358

    
2359
void helper_lddf(target_ulong addr, int mem_idx)
2360
{
2361
    helper_check_align(addr, 7);
2362
#if !defined(CONFIG_USER_ONLY)
2363
    switch (mem_idx) {
2364
    case 0:
2365
        DT0 = ldfq_user(addr);
2366
        break;
2367
    case 1:
2368
        DT0 = ldfq_kernel(addr);
2369
        break;
2370
#ifdef TARGET_SPARC64
2371
    case 2:
2372
        DT0 = ldfq_hypv(addr);
2373
        break;
2374
#endif
2375
    default:
2376
        break;
2377
    }
2378
#else
2379
    address_mask(env, &addr);
2380
    DT0 = ldfq_raw(addr);
2381
#endif
2382
}
2383

    
2384
void helper_ldqf(target_ulong addr, int mem_idx)
2385
{
2386
    // XXX add 128 bit load
2387
    CPU_QuadU u;
2388

    
2389
    helper_check_align(addr, 7);
2390
#if !defined(CONFIG_USER_ONLY)
2391
    switch (mem_idx) {
2392
    case 0:
2393
        u.ll.upper = ldq_user(addr);
2394
        u.ll.lower = ldq_user(addr + 8);
2395
        QT0 = u.q;
2396
        break;
2397
    case 1:
2398
        u.ll.upper = ldq_kernel(addr);
2399
        u.ll.lower = ldq_kernel(addr + 8);
2400
        QT0 = u.q;
2401
        break;
2402
#ifdef TARGET_SPARC64
2403
    case 2:
2404
        u.ll.upper = ldq_hypv(addr);
2405
        u.ll.lower = ldq_hypv(addr + 8);
2406
        QT0 = u.q;
2407
        break;
2408
#endif
2409
    default:
2410
        break;
2411
    }
2412
#else
2413
    address_mask(env, &addr);
2414
    u.ll.upper = ldq_raw(addr);
2415
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2416
    QT0 = u.q;
2417
#endif
2418
}
2419

    
2420
void helper_stqf(target_ulong addr, int mem_idx)
2421
{
2422
    // XXX add 128 bit store
2423
    CPU_QuadU u;
2424

    
2425
    helper_check_align(addr, 7);
2426
#if !defined(CONFIG_USER_ONLY)
2427
    switch (mem_idx) {
2428
    case 0:
2429
        u.q = QT0;
2430
        stq_user(addr, u.ll.upper);
2431
        stq_user(addr + 8, u.ll.lower);
2432
        break;
2433
    case 1:
2434
        u.q = QT0;
2435
        stq_kernel(addr, u.ll.upper);
2436
        stq_kernel(addr + 8, u.ll.lower);
2437
        break;
2438
#ifdef TARGET_SPARC64
2439
    case 2:
2440
        u.q = QT0;
2441
        stq_hypv(addr, u.ll.upper);
2442
        stq_hypv(addr + 8, u.ll.lower);
2443
        break;
2444
#endif
2445
    default:
2446
        break;
2447
    }
2448
#else
2449
    u.q = QT0;
2450
    address_mask(env, &addr);
2451
    stq_raw(addr, u.ll.upper);
2452
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2453
#endif
2454
}
2455

    
2456
static inline void set_fsr(void)
2457
{
2458
    int rnd_mode;
2459

    
2460
    switch (env->fsr & FSR_RD_MASK) {
2461
    case FSR_RD_NEAREST:
2462
        rnd_mode = float_round_nearest_even;
2463
        break;
2464
    default:
2465
    case FSR_RD_ZERO:
2466
        rnd_mode = float_round_to_zero;
2467
        break;
2468
    case FSR_RD_POS:
2469
        rnd_mode = float_round_up;
2470
        break;
2471
    case FSR_RD_NEG:
2472
        rnd_mode = float_round_down;
2473
        break;
2474
    }
2475
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2476
}
2477

    
2478
void helper_ldfsr(uint32_t new_fsr)
2479
{
2480
    env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
2481
    set_fsr();
2482
}
2483

    
2484
#ifdef TARGET_SPARC64
2485
void helper_ldxfsr(uint64_t new_fsr)
2486
{
2487
    env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
2488
    set_fsr();
2489
}
2490
#endif
2491

    
2492
void helper_debug(void)
2493
{
2494
    env->exception_index = EXCP_DEBUG;
2495
    cpu_loop_exit();
2496
}
2497

    
2498
#ifndef TARGET_SPARC64
2499
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2500
   handling ? */
2501
void helper_save(void)
2502
{
2503
    uint32_t cwp;
2504

    
2505
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2506
    if (env->wim & (1 << cwp)) {
2507
        raise_exception(TT_WIN_OVF);
2508
    }
2509
    set_cwp(cwp);
2510
}
2511

    
2512
void helper_restore(void)
2513
{
2514
    uint32_t cwp;
2515

    
2516
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2517
    if (env->wim & (1 << cwp)) {
2518
        raise_exception(TT_WIN_UNF);
2519
    }
2520
    set_cwp(cwp);
2521
}
2522

    
2523
void helper_wrpsr(target_ulong new_psr)
2524
{
2525
    if ((new_psr & PSR_CWP) >= env->nwindows)
2526
        raise_exception(TT_ILL_INSN);
2527
    else
2528
        PUT_PSR(env, new_psr);
2529
}
2530

    
2531
target_ulong helper_rdpsr(void)
2532
{
2533
    return GET_PSR(env);
2534
}
2535

    
2536
#else
2537
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2538
   handling ? */
2539
void helper_save(void)
2540
{
2541
    uint32_t cwp;
2542

    
2543
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2544
    if (env->cansave == 0) {
2545
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2546
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2547
                                    ((env->wstate & 0x7) << 2)));
2548
    } else {
2549
        if (env->cleanwin - env->canrestore == 0) {
2550
            // XXX Clean windows without trap
2551
            raise_exception(TT_CLRWIN);
2552
        } else {
2553
            env->cansave--;
2554
            env->canrestore++;
2555
            set_cwp(cwp);
2556
        }
2557
    }
2558
}
2559

    
2560
void helper_restore(void)
2561
{
2562
    uint32_t cwp;
2563

    
2564
    cwp = cpu_cwp_inc(env, env->cwp + 1);
2565
    if (env->canrestore == 0) {
2566
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2567
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2568
                                   ((env->wstate & 0x7) << 2)));
2569
    } else {
2570
        env->cansave++;
2571
        env->canrestore--;
2572
        set_cwp(cwp);
2573
    }
2574
}
2575

    
2576
void helper_flushw(void)
2577
{
2578
    if (env->cansave != env->nwindows - 2) {
2579
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2580
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2581
                                    ((env->wstate & 0x7) << 2)));
2582
    }
2583
}
2584

    
2585
void helper_saved(void)
2586
{
2587
    env->cansave++;
2588
    if (env->otherwin == 0)
2589
        env->canrestore--;
2590
    else
2591
        env->otherwin--;
2592
}
2593

    
2594
void helper_restored(void)
2595
{
2596
    env->canrestore++;
2597
    if (env->cleanwin < env->nwindows - 1)
2598
        env->cleanwin++;
2599
    if (env->otherwin == 0)
2600
        env->cansave--;
2601
    else
2602
        env->otherwin--;
2603
}
2604

    
2605
target_ulong helper_rdccr(void)
2606
{
2607
    return GET_CCR(env);
2608
}
2609

    
2610
void helper_wrccr(target_ulong new_ccr)
2611
{
2612
    PUT_CCR(env, new_ccr);
2613
}
2614

    
2615
// CWP handling is reversed in V9, but we still use the V8 register
2616
// order.
2617
target_ulong helper_rdcwp(void)
2618
{
2619
    return GET_CWP64(env);
2620
}
2621

    
2622
void helper_wrcwp(target_ulong new_cwp)
2623
{
2624
    PUT_CWP64(env, new_cwp);
2625
}
2626

    
2627
// This function uses non-native bit order
2628
#define GET_FIELD(X, FROM, TO)                                  \
2629
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2630

    
2631
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2632
#define GET_FIELD_SP(X, FROM, TO)               \
2633
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2634

    
2635
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2636
{
2637
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2638
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2639
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2640
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2641
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2642
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2643
        (((pixel_addr >> 55) & 1) << 4) |
2644
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2645
        GET_FIELD_SP(pixel_addr, 11, 12);
2646
}
2647

    
2648
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2649
{
2650
    uint64_t tmp;
2651

    
2652
    tmp = addr + offset;
2653
    env->gsr &= ~7ULL;
2654
    env->gsr |= tmp & 7ULL;
2655
    return tmp & ~7ULL;
2656
}
2657

    
2658
target_ulong helper_popc(target_ulong val)
2659
{
2660
    return ctpop64(val);
2661
}
2662

    
2663
static inline uint64_t *get_gregset(uint64_t pstate)
2664
{
2665
    switch (pstate) {
2666
    default:
2667
    case 0:
2668
        return env->bgregs;
2669
    case PS_AG:
2670
        return env->agregs;
2671
    case PS_MG:
2672
        return env->mgregs;
2673
    case PS_IG:
2674
        return env->igregs;
2675
    }
2676
}
2677

    
2678
static inline void change_pstate(uint64_t new_pstate)
2679
{
2680
    uint64_t pstate_regs, new_pstate_regs;
2681
    uint64_t *src, *dst;
2682

    
2683
    pstate_regs = env->pstate & 0xc01;
2684
    new_pstate_regs = new_pstate & 0xc01;
2685
    if (new_pstate_regs != pstate_regs) {
2686
        // Switch global register bank
2687
        src = get_gregset(new_pstate_regs);
2688
        dst = get_gregset(pstate_regs);
2689
        memcpy32(dst, env->gregs);
2690
        memcpy32(env->gregs, src);
2691
    }
2692
    env->pstate = new_pstate;
2693
}
2694

    
2695
void helper_wrpstate(target_ulong new_state)
2696
{
2697
    if (!(env->def->features & CPU_FEATURE_GL))
2698
        change_pstate(new_state & 0xf3f);
2699
}
2700

    
2701
void helper_done(void)
2702
{
2703
    env->pc = env->tsptr->tpc;
2704
    env->npc = env->tsptr->tnpc + 4;
2705
    PUT_CCR(env, env->tsptr->tstate >> 32);
2706
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2707
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2708
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2709
    env->tl--;
2710
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2711
}
2712

    
2713
void helper_retry(void)
2714
{
2715
    env->pc = env->tsptr->tpc;
2716
    env->npc = env->tsptr->tnpc;
2717
    PUT_CCR(env, env->tsptr->tstate >> 32);
2718
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2719
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2720
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2721
    env->tl--;
2722
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2723
}
2724
#endif
2725

    
2726
void helper_flush(target_ulong addr)
2727
{
2728
    addr &= ~7;
2729
    tb_invalidate_page_range(addr, addr + 8);
2730
}
2731

    
2732
#ifdef TARGET_SPARC64
2733
#ifdef DEBUG_PCALL
2734
static const char * const excp_names[0x80] = {
2735
    [TT_TFAULT] = "Instruction Access Fault",
2736
    [TT_TMISS] = "Instruction Access MMU Miss",
2737
    [TT_CODE_ACCESS] = "Instruction Access Error",
2738
    [TT_ILL_INSN] = "Illegal Instruction",
2739
    [TT_PRIV_INSN] = "Privileged Instruction",
2740
    [TT_NFPU_INSN] = "FPU Disabled",
2741
    [TT_FP_EXCP] = "FPU Exception",
2742
    [TT_TOVF] = "Tag Overflow",
2743
    [TT_CLRWIN] = "Clean Windows",
2744
    [TT_DIV_ZERO] = "Division By Zero",
2745
    [TT_DFAULT] = "Data Access Fault",
2746
    [TT_DMISS] = "Data Access MMU Miss",
2747
    [TT_DATA_ACCESS] = "Data Access Error",
2748
    [TT_DPROT] = "Data Protection Error",
2749
    [TT_UNALIGNED] = "Unaligned Memory Access",
2750
    [TT_PRIV_ACT] = "Privileged Action",
2751
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2752
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2753
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2754
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2755
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2756
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2757
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2758
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2759
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2760
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2761
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2762
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2763
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2764
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2765
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2766
};
2767
#endif
2768

    
2769
void do_interrupt(CPUState *env)
2770
{
2771
    int intno = env->exception_index;
2772

    
2773
#ifdef DEBUG_PCALL
2774
    if (loglevel & CPU_LOG_INT) {
2775
        static int count;
2776
        const char *name;
2777

    
2778
        if (intno < 0 || intno >= 0x180)
2779
            name = "Unknown";
2780
        else if (intno >= 0x100)
2781
            name = "Trap Instruction";
2782
        else if (intno >= 0xc0)
2783
            name = "Window Fill";
2784
        else if (intno >= 0x80)
2785
            name = "Window Spill";
2786
        else {
2787
            name = excp_names[intno];
2788
            if (!name)
2789
                name = "Unknown";
2790
        }
2791

    
2792
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2793
                " SP=%016" PRIx64 "\n",
2794
                count, name, intno,
2795
                env->pc,
2796
                env->npc, env->regwptr[6]);
2797
        cpu_dump_state(env, logfile, fprintf, 0);
2798
#if 0
2799
        {
2800
            int i;
2801
            uint8_t *ptr;
2802

2803
            fprintf(logfile, "       code=");
2804
            ptr = (uint8_t *)env->pc;
2805
            for(i = 0; i < 16; i++) {
2806
                fprintf(logfile, " %02x", ldub(ptr + i));
2807
            }
2808
            fprintf(logfile, "\n");
2809
        }
2810
#endif
2811
        count++;
2812
    }
2813
#endif
2814
#if !defined(CONFIG_USER_ONLY)
2815
    if (env->tl >= env->maxtl) {
2816
        cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
2817
                  " Error state", env->exception_index, env->tl, env->maxtl);
2818
        return;
2819
    }
2820
#endif
2821
    if (env->tl < env->maxtl - 1) {
2822
        env->tl++;
2823
    } else {
2824
        env->pstate |= PS_RED;
2825
        if (env->tl < env->maxtl)
2826
            env->tl++;
2827
    }
2828
    env->tsptr = &env->ts[env->tl & MAXTL_MASK];
2829
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2830
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2831
        GET_CWP64(env);
2832
    env->tsptr->tpc = env->pc;
2833
    env->tsptr->tnpc = env->npc;
2834
    env->tsptr->tt = intno;
2835
    if (!(env->def->features & CPU_FEATURE_GL)) {
2836
        switch (intno) {
2837
        case TT_IVEC:
2838
            change_pstate(PS_PEF | PS_PRIV | PS_IG);
2839
            break;
2840
        case TT_TFAULT:
2841
        case TT_TMISS:
2842
        case TT_DFAULT:
2843
        case TT_DMISS:
2844
        case TT_DPROT:
2845
            change_pstate(PS_PEF | PS_PRIV | PS_MG);
2846
            break;
2847
        default:
2848
            change_pstate(PS_PEF | PS_PRIV | PS_AG);
2849
            break;
2850
        }
2851
    }
2852
    if (intno == TT_CLRWIN)
2853
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
2854
    else if ((intno & 0x1c0) == TT_SPILL)
2855
        cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
2856
    else if ((intno & 0x1c0) == TT_FILL)
2857
        cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
2858
    env->tbr &= ~0x7fffULL;
2859
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2860
    env->pc = env->tbr;
2861
    env->npc = env->pc + 4;
2862
    env->exception_index = 0;
2863
}
2864
#else
2865
#ifdef DEBUG_PCALL
2866
static const char * const excp_names[0x80] = {
2867
    [TT_TFAULT] = "Instruction Access Fault",
2868
    [TT_ILL_INSN] = "Illegal Instruction",
2869
    [TT_PRIV_INSN] = "Privileged Instruction",
2870
    [TT_NFPU_INSN] = "FPU Disabled",
2871
    [TT_WIN_OVF] = "Window Overflow",
2872
    [TT_WIN_UNF] = "Window Underflow",
2873
    [TT_UNALIGNED] = "Unaligned Memory Access",
2874
    [TT_FP_EXCP] = "FPU Exception",
2875
    [TT_DFAULT] = "Data Access Fault",
2876
    [TT_TOVF] = "Tag Overflow",
2877
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2878
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2879
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2880
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2881
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2882
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2883
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2884
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2885
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2886
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2887
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2888
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2889
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2890
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2891
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2892
    [TT_TOVF] = "Tag Overflow",
2893
    [TT_CODE_ACCESS] = "Instruction Access Error",
2894
    [TT_DATA_ACCESS] = "Data Access Error",
2895
    [TT_DIV_ZERO] = "Division By Zero",
2896
    [TT_NCP_INSN] = "Coprocessor Disabled",
2897
};
2898
#endif
2899

    
2900
void do_interrupt(CPUState *env)
2901
{
2902
    int cwp, intno = env->exception_index;
2903

    
2904
#ifdef DEBUG_PCALL
2905
    if (loglevel & CPU_LOG_INT) {
2906
        static int count;
2907
        const char *name;
2908

    
2909
        if (intno < 0 || intno >= 0x100)
2910
            name = "Unknown";
2911
        else if (intno >= 0x80)
2912
            name = "Trap Instruction";
2913
        else {
2914
            name = excp_names[intno];
2915
            if (!name)
2916
                name = "Unknown";
2917
        }
2918

    
2919
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2920
                count, name, intno,
2921
                env->pc,
2922
                env->npc, env->regwptr[6]);
2923
        cpu_dump_state(env, logfile, fprintf, 0);
2924
#if 0
2925
        {
2926
            int i;
2927
            uint8_t *ptr;
2928

2929
            fprintf(logfile, "       code=");
2930
            ptr = (uint8_t *)env->pc;
2931
            for(i = 0; i < 16; i++) {
2932
                fprintf(logfile, " %02x", ldub(ptr + i));
2933
            }
2934
            fprintf(logfile, "\n");
2935
        }
2936
#endif
2937
        count++;
2938
    }
2939
#endif
2940
#if !defined(CONFIG_USER_ONLY)
2941
    if (env->psret == 0) {
2942
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
2943
                  env->exception_index);
2944
        return;
2945
    }
2946
#endif
2947
    env->psret = 0;
2948
    cwp = cpu_cwp_dec(env, env->cwp - 1);
2949
    cpu_set_cwp(env, cwp);
2950
    env->regwptr[9] = env->pc;
2951
    env->regwptr[10] = env->npc;
2952
    env->psrps = env->psrs;
2953
    env->psrs = 1;
2954
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2955
    env->pc = env->tbr;
2956
    env->npc = env->pc + 4;
2957
    env->exception_index = 0;
2958
}
2959
#endif
2960

    
2961
#if !defined(CONFIG_USER_ONLY)
2962

    
2963
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2964
                                void *retaddr);
2965

    
2966
#define MMUSUFFIX _mmu
2967
#define ALIGNED_ONLY
2968

    
2969
#define SHIFT 0
2970
#include "softmmu_template.h"
2971

    
2972
#define SHIFT 1
2973
#include "softmmu_template.h"
2974

    
2975
#define SHIFT 2
2976
#include "softmmu_template.h"
2977

    
2978
#define SHIFT 3
2979
#include "softmmu_template.h"
2980

    
2981
/* XXX: make it generic ? */
2982
static void cpu_restore_state2(void *retaddr)
2983
{
2984
    TranslationBlock *tb;
2985
    unsigned long pc;
2986

    
2987
    if (retaddr) {
2988
        /* now we have a real cpu fault */
2989
        pc = (unsigned long)retaddr;
2990
        tb = tb_find_pc(pc);
2991
        if (tb) {
2992
            /* the PC is inside the translated code. It means that we have
2993
               a virtual CPU fault */
2994
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
2995
        }
2996
    }
2997
}
2998

    
2999
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
3000
                                void *retaddr)
3001
{
3002
#ifdef DEBUG_UNALIGNED
3003
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
3004
           "\n", addr, env->pc);
3005
#endif
3006
    cpu_restore_state2(retaddr);
3007
    raise_exception(TT_UNALIGNED);
3008
}
3009

    
3010
/* try to fill the TLB and return an exception if error. If retaddr is
3011
   NULL, it means that the function was called in C code (i.e. not
3012
   from generated code or from helper.c) */
3013
/* XXX: fix it to restore all registers */
3014
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
3015
{
3016
    int ret;
3017
    CPUState *saved_env;
3018

    
3019
    /* XXX: hack to restore env in all cases, even if not called from
3020
       generated code */
3021
    saved_env = env;
3022
    env = cpu_single_env;
3023

    
3024
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
3025
    if (ret) {
3026
        cpu_restore_state2(retaddr);
3027
        cpu_loop_exit();
3028
    }
3029
    env = saved_env;
3030
}
3031

    
3032
#endif
3033

    
3034
#ifndef TARGET_SPARC64
3035
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3036
                          int is_asi)
3037
{
3038
    CPUState *saved_env;
3039

    
3040
    /* XXX: hack to restore env in all cases, even if not called from
3041
       generated code */
3042
    saved_env = env;
3043
    env = cpu_single_env;
3044
#ifdef DEBUG_UNASSIGNED
3045
    if (is_asi)
3046
        printf("Unassigned mem %s access to " TARGET_FMT_plx
3047
               " asi 0x%02x from " TARGET_FMT_lx "\n",
3048
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
3049
               env->pc);
3050
    else
3051
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
3052
               TARGET_FMT_lx "\n",
3053
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
3054
#endif
3055
    if (env->mmuregs[3]) /* Fault status register */
3056
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
3057
    if (is_asi)
3058
        env->mmuregs[3] |= 1 << 16;
3059
    if (env->psrs)
3060
        env->mmuregs[3] |= 1 << 5;
3061
    if (is_exec)
3062
        env->mmuregs[3] |= 1 << 6;
3063
    if (is_write)
3064
        env->mmuregs[3] |= 1 << 7;
3065
    env->mmuregs[3] |= (5 << 2) | 2;
3066
    env->mmuregs[4] = addr; /* Fault address register */
3067
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
3068
        if (is_exec)
3069
            raise_exception(TT_CODE_ACCESS);
3070
        else
3071
            raise_exception(TT_DATA_ACCESS);
3072
    }
3073
    env = saved_env;
3074
}
3075
#else
3076
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
3077
                          int is_asi)
3078
{
3079
#ifdef DEBUG_UNASSIGNED
3080
    CPUState *saved_env;
3081

    
3082
    /* XXX: hack to restore env in all cases, even if not called from
3083
       generated code */
3084
    saved_env = env;
3085
    env = cpu_single_env;
3086
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
3087
           "\n", addr, env->pc);
3088
    env = saved_env;
3089
#endif
3090
    if (is_exec)
3091
        raise_exception(TT_CODE_ACCESS);
3092
    else
3093
        raise_exception(TT_DATA_ACCESS);
3094
}
3095
#endif
3096