Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 8686c490

History | View | Annotate | Download (80 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_PCALL
9
//#define DEBUG_MMU
10
//#define DEBUG_MXCC
11
//#define DEBUG_UNALIGNED
12
//#define DEBUG_UNASSIGNED
13
//#define DEBUG_ASI
14

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

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

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

    
36
#ifdef TARGET_ABI32
37
#define ABI32_MASK(addr) do { (addr) &= 0xffffffffULL; } while (0)
38
#else
39
#define ABI32_MASK(addr) do {} while (0)
40
#endif
41

    
42
void raise_exception(int tt)
43
{
44
    env->exception_index = tt;
45
    cpu_loop_exit();
46
}
47

    
48
void helper_trap(target_ulong nb_trap)
49
{
50
    env->exception_index = TT_TRAP + (nb_trap & 0x7f);
51
    cpu_loop_exit();
52
}
53

    
54
void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
55
{
56
    if (do_trap) {
57
        env->exception_index = TT_TRAP + (nb_trap & 0x7f);
58
        cpu_loop_exit();
59
    }
60
}
61

    
62
void helper_check_align(target_ulong addr, uint32_t align)
63
{
64
    if (addr & align) {
65
#ifdef DEBUG_UNALIGNED
66
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
67
           "\n", addr, env->pc);
68
#endif
69
        raise_exception(TT_UNALIGNED);
70
    }
71
}
72

    
73
#define F_HELPER(name, p) void helper_f##name##p(void)
74

    
75
#define F_BINOP(name)                                           \
76
    F_HELPER(name, s)                                           \
77
    {                                                           \
78
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
79
    }                                                           \
80
    F_HELPER(name, d)                                           \
81
    {                                                           \
82
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
83
    }                                                           \
84
    F_HELPER(name, q)                                           \
85
    {                                                           \
86
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
87
    }
88

    
89
F_BINOP(add);
90
F_BINOP(sub);
91
F_BINOP(mul);
92
F_BINOP(div);
93
#undef F_BINOP
94

    
95
void helper_fsmuld(void)
96
{
97
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
98
                      float32_to_float64(FT1, &env->fp_status),
99
                      &env->fp_status);
100
}
101

    
102
void helper_fdmulq(void)
103
{
104
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
105
                       float64_to_float128(DT1, &env->fp_status),
106
                       &env->fp_status);
107
}
108

    
109
F_HELPER(neg, s)
110
{
111
    FT0 = float32_chs(FT1);
112
}
113

    
114
#ifdef TARGET_SPARC64
115
F_HELPER(neg, d)
116
{
117
    DT0 = float64_chs(DT1);
118
}
119

    
120
F_HELPER(neg, q)
121
{
122
    QT0 = float128_chs(QT1);
123
}
124
#endif
125

    
126
/* Integer to float conversion.  */
127
F_HELPER(ito, s)
128
{
129
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
130
}
131

    
132
F_HELPER(ito, d)
133
{
134
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
135
}
136

    
137
F_HELPER(ito, q)
138
{
139
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
140
}
141

    
142
#ifdef TARGET_SPARC64
143
F_HELPER(xto, s)
144
{
145
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
146
}
147

    
148
F_HELPER(xto, d)
149
{
150
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
151
}
152

    
153
F_HELPER(xto, q)
154
{
155
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
156
}
157
#endif
158
#undef F_HELPER
159

    
160
/* floating point conversion */
161
void helper_fdtos(void)
162
{
163
    FT0 = float64_to_float32(DT1, &env->fp_status);
164
}
165

    
166
void helper_fstod(void)
167
{
168
    DT0 = float32_to_float64(FT1, &env->fp_status);
169
}
170

    
171
void helper_fqtos(void)
172
{
173
    FT0 = float128_to_float32(QT1, &env->fp_status);
174
}
175

    
176
void helper_fstoq(void)
177
{
178
    QT0 = float32_to_float128(FT1, &env->fp_status);
179
}
180

    
181
void helper_fqtod(void)
182
{
183
    DT0 = float128_to_float64(QT1, &env->fp_status);
184
}
185

    
186
void helper_fdtoq(void)
187
{
188
    QT0 = float64_to_float128(DT1, &env->fp_status);
189
}
190

    
191
/* Float to integer conversion.  */
192
void helper_fstoi(void)
193
{
194
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
195
}
196

    
197
void helper_fdtoi(void)
198
{
199
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
200
}
201

    
202
void helper_fqtoi(void)
203
{
204
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
205
}
206

    
207
#ifdef TARGET_SPARC64
208
void helper_fstox(void)
209
{
210
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
211
}
212

    
213
void helper_fdtox(void)
214
{
215
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
216
}
217

    
218
void helper_fqtox(void)
219
{
220
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
221
}
222

    
223
void helper_faligndata(void)
224
{
225
    uint64_t tmp;
226

    
227
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
228
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
229
    *((uint64_t *)&DT0) = tmp;
230
}
231

    
232
void helper_movl_FT0_0(void)
233
{
234
    *((uint32_t *)&FT0) = 0;
235
}
236

    
237
void helper_movl_DT0_0(void)
238
{
239
    *((uint64_t *)&DT0) = 0;
240
}
241

    
242
void helper_movl_FT0_1(void)
243
{
244
    *((uint32_t *)&FT0) = 0xffffffff;
245
}
246

    
247
void helper_movl_DT0_1(void)
248
{
249
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
250
}
251

    
252
void helper_fnot(void)
253
{
254
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
255
}
256

    
257
void helper_fnots(void)
258
{
259
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
260
}
261

    
262
void helper_fnor(void)
263
{
264
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
265
}
266

    
267
void helper_fnors(void)
268
{
269
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
270
}
271

    
272
void helper_for(void)
273
{
274
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
275
}
276

    
277
void helper_fors(void)
278
{
279
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
280
}
281

    
282
void helper_fxor(void)
283
{
284
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
285
}
286

    
287
void helper_fxors(void)
288
{
289
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
290
}
291

    
292
void helper_fand(void)
293
{
294
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
295
}
296

    
297
void helper_fands(void)
298
{
299
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
300
}
301

    
302
void helper_fornot(void)
303
{
304
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
305
}
306

    
307
void helper_fornots(void)
308
{
309
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
310
}
311

    
312
void helper_fandnot(void)
313
{
314
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
315
}
316

    
317
void helper_fandnots(void)
318
{
319
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
320
}
321

    
322
void helper_fnand(void)
323
{
324
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
325
}
326

    
327
void helper_fnands(void)
328
{
329
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
330
}
331

    
332
void helper_fxnor(void)
333
{
334
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
335
}
336

    
337
void helper_fxnors(void)
338
{
339
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
340
}
341

    
342
#ifdef WORDS_BIGENDIAN
343
#define VIS_B64(n) b[7 - (n)]
344
#define VIS_W64(n) w[3 - (n)]
345
#define VIS_SW64(n) sw[3 - (n)]
346
#define VIS_L64(n) l[1 - (n)]
347
#define VIS_B32(n) b[3 - (n)]
348
#define VIS_W32(n) w[1 - (n)]
349
#else
350
#define VIS_B64(n) b[n]
351
#define VIS_W64(n) w[n]
352
#define VIS_SW64(n) sw[n]
353
#define VIS_L64(n) l[n]
354
#define VIS_B32(n) b[n]
355
#define VIS_W32(n) w[n]
356
#endif
357

    
358
typedef union {
359
    uint8_t b[8];
360
    uint16_t w[4];
361
    int16_t sw[4];
362
    uint32_t l[2];
363
    float64 d;
364
} vis64;
365

    
366
typedef union {
367
    uint8_t b[4];
368
    uint16_t w[2];
369
    uint32_t l;
370
    float32 f;
371
} vis32;
372

    
373
void helper_fpmerge(void)
374
{
375
    vis64 s, d;
376

    
377
    s.d = DT0;
378
    d.d = DT1;
379

    
380
    // Reverse calculation order to handle overlap
381
    d.VIS_B64(7) = s.VIS_B64(3);
382
    d.VIS_B64(6) = d.VIS_B64(3);
383
    d.VIS_B64(5) = s.VIS_B64(2);
384
    d.VIS_B64(4) = d.VIS_B64(2);
385
    d.VIS_B64(3) = s.VIS_B64(1);
386
    d.VIS_B64(2) = d.VIS_B64(1);
387
    d.VIS_B64(1) = s.VIS_B64(0);
388
    //d.VIS_B64(0) = d.VIS_B64(0);
389

    
390
    DT0 = d.d;
391
}
392

    
393
void helper_fmul8x16(void)
394
{
395
    vis64 s, d;
396
    uint32_t tmp;
397

    
398
    s.d = DT0;
399
    d.d = DT1;
400

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

    
407
    PMUL(0);
408
    PMUL(1);
409
    PMUL(2);
410
    PMUL(3);
411
#undef PMUL
412

    
413
    DT0 = d.d;
414
}
415

    
416
void helper_fmul8x16al(void)
417
{
418
    vis64 s, d;
419
    uint32_t tmp;
420

    
421
    s.d = DT0;
422
    d.d = DT1;
423

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

    
430
    PMUL(0);
431
    PMUL(1);
432
    PMUL(2);
433
    PMUL(3);
434
#undef PMUL
435

    
436
    DT0 = d.d;
437
}
438

    
439
void helper_fmul8x16au(void)
440
{
441
    vis64 s, d;
442
    uint32_t tmp;
443

    
444
    s.d = DT0;
445
    d.d = DT1;
446

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

    
453
    PMUL(0);
454
    PMUL(1);
455
    PMUL(2);
456
    PMUL(3);
457
#undef PMUL
458

    
459
    DT0 = d.d;
460
}
461

    
462
void helper_fmul8sux16(void)
463
{
464
    vis64 s, d;
465
    uint32_t tmp;
466

    
467
    s.d = DT0;
468
    d.d = DT1;
469

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

    
476
    PMUL(0);
477
    PMUL(1);
478
    PMUL(2);
479
    PMUL(3);
480
#undef PMUL
481

    
482
    DT0 = d.d;
483
}
484

    
485
void helper_fmul8ulx16(void)
486
{
487
    vis64 s, d;
488
    uint32_t tmp;
489

    
490
    s.d = DT0;
491
    d.d = DT1;
492

    
493
#define PMUL(r)                                                         \
494
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
495
    if ((tmp & 0xff) > 0x7f)                                            \
496
        tmp += 0x100;                                                   \
497
    d.VIS_W64(r) = tmp >> 8;
498

    
499
    PMUL(0);
500
    PMUL(1);
501
    PMUL(2);
502
    PMUL(3);
503
#undef PMUL
504

    
505
    DT0 = d.d;
506
}
507

    
508
void helper_fmuld8sux16(void)
509
{
510
    vis64 s, d;
511
    uint32_t tmp;
512

    
513
    s.d = DT0;
514
    d.d = DT1;
515

    
516
#define PMUL(r)                                                         \
517
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
518
    if ((tmp & 0xff) > 0x7f)                                            \
519
        tmp += 0x100;                                                   \
520
    d.VIS_L64(r) = tmp;
521

    
522
    // Reverse calculation order to handle overlap
523
    PMUL(1);
524
    PMUL(0);
525
#undef PMUL
526

    
527
    DT0 = d.d;
528
}
529

    
530
void helper_fmuld8ulx16(void)
531
{
532
    vis64 s, d;
533
    uint32_t tmp;
534

    
535
    s.d = DT0;
536
    d.d = DT1;
537

    
538
#define PMUL(r)                                                         \
539
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
540
    if ((tmp & 0xff) > 0x7f)                                            \
541
        tmp += 0x100;                                                   \
542
    d.VIS_L64(r) = tmp;
543

    
544
    // Reverse calculation order to handle overlap
545
    PMUL(1);
546
    PMUL(0);
547
#undef PMUL
548

    
549
    DT0 = d.d;
550
}
551

    
552
void helper_fexpand(void)
553
{
554
    vis32 s;
555
    vis64 d;
556

    
557
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
558
    d.d = DT1;
559
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
560
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
561
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
562
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
563

    
564
    DT0 = d.d;
565
}
566

    
567
#define VIS_HELPER(name, F)                             \
568
    void name##16(void)                                 \
569
    {                                                   \
570
        vis64 s, d;                                     \
571
                                                        \
572
        s.d = DT0;                                      \
573
        d.d = DT1;                                      \
574
                                                        \
575
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
576
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
577
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
578
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
579
                                                        \
580
        DT0 = d.d;                                      \
581
    }                                                   \
582
                                                        \
583
    void name##16s(void)                                \
584
    {                                                   \
585
        vis32 s, d;                                     \
586
                                                        \
587
        s.f = FT0;                                      \
588
        d.f = FT1;                                      \
589
                                                        \
590
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
591
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
592
                                                        \
593
        FT0 = d.f;                                      \
594
    }                                                   \
595
                                                        \
596
    void name##32(void)                                 \
597
    {                                                   \
598
        vis64 s, d;                                     \
599
                                                        \
600
        s.d = DT0;                                      \
601
        d.d = DT1;                                      \
602
                                                        \
603
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
604
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
605
                                                        \
606
        DT0 = d.d;                                      \
607
    }                                                   \
608
                                                        \
609
    void name##32s(void)                                \
610
    {                                                   \
611
        vis32 s, d;                                     \
612
                                                        \
613
        s.f = FT0;                                      \
614
        d.f = FT1;                                      \
615
                                                        \
616
        d.l = F(d.l, s.l);                              \
617
                                                        \
618
        FT0 = d.f;                                      \
619
    }
620

    
621
#define FADD(a, b) ((a) + (b))
622
#define FSUB(a, b) ((a) - (b))
623
VIS_HELPER(helper_fpadd, FADD)
624
VIS_HELPER(helper_fpsub, FSUB)
625

    
626
#define VIS_CMPHELPER(name, F)                                        \
627
    void name##16(void)                                           \
628
    {                                                             \
629
        vis64 s, d;                                               \
630
                                                                  \
631
        s.d = DT0;                                                \
632
        d.d = DT1;                                                \
633
                                                                  \
634
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
635
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
636
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
637
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
638
                                                                  \
639
        DT0 = d.d;                                                \
640
    }                                                             \
641
                                                                  \
642
    void name##32(void)                                           \
643
    {                                                             \
644
        vis64 s, d;                                               \
645
                                                                  \
646
        s.d = DT0;                                                \
647
        d.d = DT1;                                                \
648
                                                                  \
649
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
650
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
651
                                                                  \
652
        DT0 = d.d;                                                \
653
    }
654

    
655
#define FCMPGT(a, b) ((a) > (b))
656
#define FCMPEQ(a, b) ((a) == (b))
657
#define FCMPLE(a, b) ((a) <= (b))
658
#define FCMPNE(a, b) ((a) != (b))
659

    
660
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
661
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
662
VIS_CMPHELPER(helper_fcmple, FCMPLE)
663
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
664
#endif
665

    
666
void helper_check_ieee_exceptions(void)
667
{
668
    target_ulong status;
669

    
670
    status = get_float_exception_flags(&env->fp_status);
671
    if (status) {
672
        /* Copy IEEE 754 flags into FSR */
673
        if (status & float_flag_invalid)
674
            env->fsr |= FSR_NVC;
675
        if (status & float_flag_overflow)
676
            env->fsr |= FSR_OFC;
677
        if (status & float_flag_underflow)
678
            env->fsr |= FSR_UFC;
679
        if (status & float_flag_divbyzero)
680
            env->fsr |= FSR_DZC;
681
        if (status & float_flag_inexact)
682
            env->fsr |= FSR_NXC;
683

    
684
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
685
            /* Unmasked exception, generate a trap */
686
            env->fsr |= FSR_FTT_IEEE_EXCP;
687
            raise_exception(TT_FP_EXCP);
688
        } else {
689
            /* Accumulate exceptions */
690
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
691
        }
692
    }
693
}
694

    
695
void helper_clear_float_exceptions(void)
696
{
697
    set_float_exception_flags(0, &env->fp_status);
698
}
699

    
700
void helper_fabss(void)
701
{
702
    FT0 = float32_abs(FT1);
703
}
704

    
705
#ifdef TARGET_SPARC64
706
void helper_fabsd(void)
707
{
708
    DT0 = float64_abs(DT1);
709
}
710

    
711
void helper_fabsq(void)
712
{
713
    QT0 = float128_abs(QT1);
714
}
715
#endif
716

    
717
void helper_fsqrts(void)
718
{
719
    FT0 = float32_sqrt(FT1, &env->fp_status);
720
}
721

    
722
void helper_fsqrtd(void)
723
{
724
    DT0 = float64_sqrt(DT1, &env->fp_status);
725
}
726

    
727
void helper_fsqrtq(void)
728
{
729
    QT0 = float128_sqrt(QT1, &env->fp_status);
730
}
731

    
732
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
733
    void glue(helper_, name) (void)                                     \
734
    {                                                                   \
735
        target_ulong new_fsr;                                           \
736
                                                                        \
737
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
738
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
739
        case float_relation_unordered:                                  \
740
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
741
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
742
                env->fsr |= new_fsr;                                    \
743
                env->fsr |= FSR_NVC;                                    \
744
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
745
                raise_exception(TT_FP_EXCP);                            \
746
            } else {                                                    \
747
                env->fsr |= FSR_NVA;                                    \
748
            }                                                           \
749
            break;                                                      \
750
        case float_relation_less:                                       \
751
            new_fsr = FSR_FCC0 << FS;                                   \
752
            break;                                                      \
753
        case float_relation_greater:                                    \
754
            new_fsr = FSR_FCC1 << FS;                                   \
755
            break;                                                      \
756
        default:                                                        \
757
            new_fsr = 0;                                                \
758
            break;                                                      \
759
        }                                                               \
760
        env->fsr |= new_fsr;                                            \
761
    }
762

    
763
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
764
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
765

    
766
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
767
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
768

    
769
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
770
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
771

    
772
#ifdef TARGET_SPARC64
773
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
774
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
775
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
776

    
777
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
778
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
779
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
780

    
781
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
782
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
783
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
784

    
785
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
786
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
787
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
788

    
789
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
790
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
791
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
792

    
793
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
794
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
795
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
796
#endif
797

    
798
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
799
static void dump_mxcc(CPUState *env)
800
{
801
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
802
        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
803
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
804
           "          %016llx %016llx %016llx %016llx\n",
805
        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
806
        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
807
}
808
#endif
809

    
810
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
811
    && defined(DEBUG_ASI)
812
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
813
                     uint64_t r1)
814
{
815
    switch (size)
816
    {
817
    case 1:
818
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
819
                    addr, asi, r1 & 0xff);
820
        break;
821
    case 2:
822
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
823
                    addr, asi, r1 & 0xffff);
824
        break;
825
    case 4:
826
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
827
                    addr, asi, r1 & 0xffffffff);
828
        break;
829
    case 8:
830
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
831
                    addr, asi, r1);
832
        break;
833
    }
834
}
835
#endif
836

    
837
#ifndef TARGET_SPARC64
838
#ifndef CONFIG_USER_ONLY
839
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
840
{
841
    uint64_t ret = 0;
842
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
843
    uint32_t last_addr = addr;
844
#endif
845

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

    
889
            mmulev = (addr >> 8) & 15;
890
            if (mmulev > 4)
891
                ret = 0;
892
            else
893
                ret = mmu_probe(env, addr, mmulev);
894
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
895
                        addr, mmulev, ret);
896
        }
897
        break;
898
    case 4: /* read MMU regs */
899
        {
900
            int reg = (addr >> 8) & 0x1f;
901

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

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

    
1131
            mmulev = (addr >> 8) & 15;
1132
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1133
            switch (mmulev) {
1134
            case 0: // flush page
1135
                tlb_flush_page(env, addr & 0xfffff000);
1136
                break;
1137
            case 1: // flush segment (256k)
1138
            case 2: // flush region (16M)
1139
            case 3: // flush context (4G)
1140
            case 4: // flush entire
1141
                tlb_flush(env, 1);
1142
                break;
1143
            default:
1144
                break;
1145
            }
1146
#ifdef DEBUG_MMU
1147
            dump_mmu(env);
1148
#endif
1149
        }
1150
        break;
1151
    case 4: /* write MMU regs */
1152
        {
1153
            int reg = (addr >> 8) & 0x1f;
1154
            uint32_t oldreg;
1155

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

    
1258
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1259
                temp = ldl_kernel(src);
1260
                stl_kernel(dst, temp);
1261
            }
1262
        }
1263
        break;
1264
    case 0x1f: /* Block fill, stda access */
1265
        {
1266
            // addr = dst
1267
            // fill 32 bytes with val
1268
            unsigned int i;
1269
            uint32_t dst = addr & 7;
1270

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

    
1337
#endif /* CONFIG_USER_ONLY */
1338
#else /* TARGET_SPARC64 */
1339

    
1340
#ifdef CONFIG_USER_ONLY
1341
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1342
{
1343
    uint64_t ret = 0;
1344
#if defined(DEBUG_ASI)
1345
    target_ulong last_addr = addr;
1346
#endif
1347

    
1348
    if (asi < 0x80)
1349
        raise_exception(TT_PRIV_ACT);
1350

    
1351
    helper_check_align(addr, size - 1);
1352
    ABI32_MASK(addr);
1353

    
1354
    switch (asi) {
1355
    case 0x80: // Primary
1356
    case 0x82: // Primary no-fault
1357
    case 0x88: // Primary LE
1358
    case 0x8a: // Primary no-fault LE
1359
        {
1360
            switch(size) {
1361
            case 1:
1362
                ret = ldub_raw(addr);
1363
                break;
1364
            case 2:
1365
                ret = lduw_raw(addr & ~1);
1366
                break;
1367
            case 4:
1368
                ret = ldl_raw(addr & ~3);
1369
                break;
1370
            default:
1371
            case 8:
1372
                ret = ldq_raw(addr & ~7);
1373
                break;
1374
            }
1375
        }
1376
        break;
1377
    case 0x81: // Secondary
1378
    case 0x83: // Secondary no-fault
1379
    case 0x89: // Secondary LE
1380
    case 0x8b: // Secondary no-fault LE
1381
        // XXX
1382
        break;
1383
    default:
1384
        break;
1385
    }
1386

    
1387
    /* Convert from little endian */
1388
    switch (asi) {
1389
    case 0x88: // Primary LE
1390
    case 0x89: // Secondary LE
1391
    case 0x8a: // Primary no-fault LE
1392
    case 0x8b: // Secondary no-fault LE
1393
        switch(size) {
1394
        case 2:
1395
            ret = bswap16(ret);
1396
            break;
1397
        case 4:
1398
            ret = bswap32(ret);
1399
            break;
1400
        case 8:
1401
            ret = bswap64(ret);
1402
            break;
1403
        default:
1404
            break;
1405
        }
1406
    default:
1407
        break;
1408
    }
1409

    
1410
    /* Convert to signed number */
1411
    if (sign) {
1412
        switch(size) {
1413
        case 1:
1414
            ret = (int8_t) ret;
1415
            break;
1416
        case 2:
1417
            ret = (int16_t) ret;
1418
            break;
1419
        case 4:
1420
            ret = (int32_t) ret;
1421
            break;
1422
        default:
1423
            break;
1424
        }
1425
    }
1426
#ifdef DEBUG_ASI
1427
    dump_asi("read ", last_addr, asi, size, ret);
1428
#endif
1429
    return ret;
1430
}
1431

    
1432
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1433
{
1434
#ifdef DEBUG_ASI
1435
    dump_asi("write", addr, asi, size, val);
1436
#endif
1437
    if (asi < 0x80)
1438
        raise_exception(TT_PRIV_ACT);
1439

    
1440
    helper_check_align(addr, size - 1);
1441
    ABI32_MASK(addr);
1442

    
1443
    /* Convert to little endian */
1444
    switch (asi) {
1445
    case 0x88: // Primary LE
1446
    case 0x89: // Secondary LE
1447
        switch(size) {
1448
        case 2:
1449
            addr = bswap16(addr);
1450
            break;
1451
        case 4:
1452
            addr = bswap32(addr);
1453
            break;
1454
        case 8:
1455
            addr = bswap64(addr);
1456
            break;
1457
        default:
1458
            break;
1459
        }
1460
    default:
1461
        break;
1462
    }
1463

    
1464
    switch(asi) {
1465
    case 0x80: // Primary
1466
    case 0x88: // Primary LE
1467
        {
1468
            switch(size) {
1469
            case 1:
1470
                stb_raw(addr, val);
1471
                break;
1472
            case 2:
1473
                stw_raw(addr & ~1, val);
1474
                break;
1475
            case 4:
1476
                stl_raw(addr & ~3, val);
1477
                break;
1478
            case 8:
1479
            default:
1480
                stq_raw(addr & ~7, val);
1481
                break;
1482
            }
1483
        }
1484
        break;
1485
    case 0x81: // Secondary
1486
    case 0x89: // Secondary LE
1487
        // XXX
1488
        return;
1489

    
1490
    case 0x82: // Primary no-fault, RO
1491
    case 0x83: // Secondary no-fault, RO
1492
    case 0x8a: // Primary no-fault LE, RO
1493
    case 0x8b: // Secondary no-fault LE, RO
1494
    default:
1495
        do_unassigned_access(addr, 1, 0, 1);
1496
        return;
1497
    }
1498
}
1499

    
1500
#else /* CONFIG_USER_ONLY */
1501

    
1502
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1503
{
1504
    uint64_t ret = 0;
1505
#if defined(DEBUG_ASI)
1506
    target_ulong last_addr = addr;
1507
#endif
1508

    
1509
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1510
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1511
        raise_exception(TT_PRIV_ACT);
1512

    
1513
    helper_check_align(addr, size - 1);
1514
    switch (asi) {
1515
    case 0x10: // As if user primary
1516
    case 0x18: // As if user primary LE
1517
    case 0x80: // Primary
1518
    case 0x82: // Primary no-fault
1519
    case 0x88: // Primary LE
1520
    case 0x8a: // Primary no-fault LE
1521
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1522
            if (env->hpstate & HS_PRIV) {
1523
                switch(size) {
1524
                case 1:
1525
                    ret = ldub_hypv(addr);
1526
                    break;
1527
                case 2:
1528
                    ret = lduw_hypv(addr & ~1);
1529
                    break;
1530
                case 4:
1531
                    ret = ldl_hypv(addr & ~3);
1532
                    break;
1533
                default:
1534
                case 8:
1535
                    ret = ldq_hypv(addr & ~7);
1536
                    break;
1537
                }
1538
            } else {
1539
                switch(size) {
1540
                case 1:
1541
                    ret = ldub_kernel(addr);
1542
                    break;
1543
                case 2:
1544
                    ret = lduw_kernel(addr & ~1);
1545
                    break;
1546
                case 4:
1547
                    ret = ldl_kernel(addr & ~3);
1548
                    break;
1549
                default:
1550
                case 8:
1551
                    ret = ldq_kernel(addr & ~7);
1552
                    break;
1553
                }
1554
            }
1555
        } else {
1556
            switch(size) {
1557
            case 1:
1558
                ret = ldub_user(addr);
1559
                break;
1560
            case 2:
1561
                ret = lduw_user(addr & ~1);
1562
                break;
1563
            case 4:
1564
                ret = ldl_user(addr & ~3);
1565
                break;
1566
            default:
1567
            case 8:
1568
                ret = ldq_user(addr & ~7);
1569
                break;
1570
            }
1571
        }
1572
        break;
1573
    case 0x14: // Bypass
1574
    case 0x15: // Bypass, non-cacheable
1575
    case 0x1c: // Bypass LE
1576
    case 0x1d: // Bypass, non-cacheable LE
1577
        {
1578
            switch(size) {
1579
            case 1:
1580
                ret = ldub_phys(addr);
1581
                break;
1582
            case 2:
1583
                ret = lduw_phys(addr & ~1);
1584
                break;
1585
            case 4:
1586
                ret = ldl_phys(addr & ~3);
1587
                break;
1588
            default:
1589
            case 8:
1590
                ret = ldq_phys(addr & ~7);
1591
                break;
1592
            }
1593
            break;
1594
        }
1595
    case 0x04: // Nucleus
1596
    case 0x0c: // Nucleus Little Endian (LE)
1597
    case 0x11: // As if user secondary
1598
    case 0x19: // As if user secondary LE
1599
    case 0x24: // Nucleus quad LDD 128 bit atomic
1600
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1601
    case 0x4a: // UPA config
1602
    case 0x81: // Secondary
1603
    case 0x83: // Secondary no-fault
1604
    case 0x89: // Secondary LE
1605
    case 0x8b: // Secondary no-fault LE
1606
        // XXX
1607
        break;
1608
    case 0x45: // LSU
1609
        ret = env->lsu;
1610
        break;
1611
    case 0x50: // I-MMU regs
1612
        {
1613
            int reg = (addr >> 3) & 0xf;
1614

    
1615
            ret = env->immuregs[reg];
1616
            break;
1617
        }
1618
    case 0x51: // I-MMU 8k TSB pointer
1619
    case 0x52: // I-MMU 64k TSB pointer
1620
    case 0x55: // I-MMU data access
1621
        // XXX
1622
        break;
1623
    case 0x56: // I-MMU tag read
1624
        {
1625
            unsigned int i;
1626

    
1627
            for (i = 0; i < 64; i++) {
1628
                // Valid, ctx match, vaddr match
1629
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1630
                    env->itlb_tag[i] == addr) {
1631
                    ret = env->itlb_tag[i];
1632
                    break;
1633
                }
1634
            }
1635
            break;
1636
        }
1637
    case 0x58: // D-MMU regs
1638
        {
1639
            int reg = (addr >> 3) & 0xf;
1640

    
1641
            ret = env->dmmuregs[reg];
1642
            break;
1643
        }
1644
    case 0x5e: // D-MMU tag read
1645
        {
1646
            unsigned int i;
1647

    
1648
            for (i = 0; i < 64; i++) {
1649
                // Valid, ctx match, vaddr match
1650
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1651
                    env->dtlb_tag[i] == addr) {
1652
                    ret = env->dtlb_tag[i];
1653
                    break;
1654
                }
1655
            }
1656
            break;
1657
        }
1658
    case 0x59: // D-MMU 8k TSB pointer
1659
    case 0x5a: // D-MMU 64k TSB pointer
1660
    case 0x5b: // D-MMU data pointer
1661
    case 0x5d: // D-MMU data access
1662
    case 0x48: // Interrupt dispatch, RO
1663
    case 0x49: // Interrupt data receive
1664
    case 0x7f: // Incoming interrupt vector, RO
1665
        // XXX
1666
        break;
1667
    case 0x54: // I-MMU data in, WO
1668
    case 0x57: // I-MMU demap, WO
1669
    case 0x5c: // D-MMU data in, WO
1670
    case 0x5f: // D-MMU demap, WO
1671
    case 0x77: // Interrupt vector, WO
1672
    default:
1673
        do_unassigned_access(addr, 0, 0, 1);
1674
        ret = 0;
1675
        break;
1676
    }
1677

    
1678
    /* Convert from little endian */
1679
    switch (asi) {
1680
    case 0x0c: // Nucleus Little Endian (LE)
1681
    case 0x18: // As if user primary LE
1682
    case 0x19: // As if user secondary LE
1683
    case 0x1c: // Bypass LE
1684
    case 0x1d: // Bypass, non-cacheable LE
1685
    case 0x88: // Primary LE
1686
    case 0x89: // Secondary LE
1687
    case 0x8a: // Primary no-fault LE
1688
    case 0x8b: // Secondary no-fault LE
1689
        switch(size) {
1690
        case 2:
1691
            ret = bswap16(ret);
1692
            break;
1693
        case 4:
1694
            ret = bswap32(ret);
1695
            break;
1696
        case 8:
1697
            ret = bswap64(ret);
1698
            break;
1699
        default:
1700
            break;
1701
        }
1702
    default:
1703
        break;
1704
    }
1705

    
1706
    /* Convert to signed number */
1707
    if (sign) {
1708
        switch(size) {
1709
        case 1:
1710
            ret = (int8_t) ret;
1711
            break;
1712
        case 2:
1713
            ret = (int16_t) ret;
1714
            break;
1715
        case 4:
1716
            ret = (int32_t) ret;
1717
            break;
1718
        default:
1719
            break;
1720
        }
1721
    }
1722
#ifdef DEBUG_ASI
1723
    dump_asi("read ", last_addr, asi, size, ret);
1724
#endif
1725
    return ret;
1726
}
1727

    
1728
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1729
{
1730
#ifdef DEBUG_ASI
1731
    dump_asi("write", addr, asi, size, val);
1732
#endif
1733
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1734
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1735
        raise_exception(TT_PRIV_ACT);
1736

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

    
1764
    switch(asi) {
1765
    case 0x10: // As if user primary
1766
    case 0x18: // As if user primary LE
1767
    case 0x80: // Primary
1768
    case 0x88: // Primary LE
1769
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1770
            if (env->hpstate & HS_PRIV) {
1771
                switch(size) {
1772
                case 1:
1773
                    stb_hypv(addr, val);
1774
                    break;
1775
                case 2:
1776
                    stw_hypv(addr & ~1, val);
1777
                    break;
1778
                case 4:
1779
                    stl_hypv(addr & ~3, val);
1780
                    break;
1781
                case 8:
1782
                default:
1783
                    stq_hypv(addr & ~7, val);
1784
                    break;
1785
                }
1786
            } else {
1787
                switch(size) {
1788
                case 1:
1789
                    stb_kernel(addr, val);
1790
                    break;
1791
                case 2:
1792
                    stw_kernel(addr & ~1, val);
1793
                    break;
1794
                case 4:
1795
                    stl_kernel(addr & ~3, val);
1796
                    break;
1797
                case 8:
1798
                default:
1799
                    stq_kernel(addr & ~7, val);
1800
                    break;
1801
                }
1802
            }
1803
        } else {
1804
            switch(size) {
1805
            case 1:
1806
                stb_user(addr, val);
1807
                break;
1808
            case 2:
1809
                stw_user(addr & ~1, val);
1810
                break;
1811
            case 4:
1812
                stl_user(addr & ~3, val);
1813
                break;
1814
            case 8:
1815
            default:
1816
                stq_user(addr & ~7, val);
1817
                break;
1818
            }
1819
        }
1820
        break;
1821
    case 0x14: // Bypass
1822
    case 0x15: // Bypass, non-cacheable
1823
    case 0x1c: // Bypass LE
1824
    case 0x1d: // Bypass, non-cacheable LE
1825
        {
1826
            switch(size) {
1827
            case 1:
1828
                stb_phys(addr, val);
1829
                break;
1830
            case 2:
1831
                stw_phys(addr & ~1, val);
1832
                break;
1833
            case 4:
1834
                stl_phys(addr & ~3, val);
1835
                break;
1836
            case 8:
1837
            default:
1838
                stq_phys(addr & ~7, val);
1839
                break;
1840
            }
1841
        }
1842
        return;
1843
    case 0x04: // Nucleus
1844
    case 0x0c: // Nucleus Little Endian (LE)
1845
    case 0x11: // As if user secondary
1846
    case 0x19: // As if user secondary LE
1847
    case 0x24: // Nucleus quad LDD 128 bit atomic
1848
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1849
    case 0x4a: // UPA config
1850
    case 0x81: // Secondary
1851
    case 0x89: // Secondary LE
1852
        // XXX
1853
        return;
1854
    case 0x45: // LSU
1855
        {
1856
            uint64_t oldreg;
1857

    
1858
            oldreg = env->lsu;
1859
            env->lsu = val & (DMMU_E | IMMU_E);
1860
            // Mappings generated during D/I MMU disabled mode are
1861
            // invalid in normal mode
1862
            if (oldreg != env->lsu) {
1863
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1864
#ifdef DEBUG_MMU
1865
                dump_mmu(env);
1866
#endif
1867
                tlb_flush(env, 1);
1868
            }
1869
            return;
1870
        }
1871
    case 0x50: // I-MMU regs
1872
        {
1873
            int reg = (addr >> 3) & 0xf;
1874
            uint64_t oldreg;
1875

    
1876
            oldreg = env->immuregs[reg];
1877
            switch(reg) {
1878
            case 0: // RO
1879
            case 4:
1880
                return;
1881
            case 1: // Not in I-MMU
1882
            case 2:
1883
            case 7:
1884
            case 8:
1885
                return;
1886
            case 3: // SFSR
1887
                if ((val & 1) == 0)
1888
                    val = 0; // Clear SFSR
1889
                break;
1890
            case 5: // TSB access
1891
            case 6: // Tag access
1892
            default:
1893
                break;
1894
            }
1895
            env->immuregs[reg] = val;
1896
            if (oldreg != env->immuregs[reg]) {
1897
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1898
            }
1899
#ifdef DEBUG_MMU
1900
            dump_mmu(env);
1901
#endif
1902
            return;
1903
        }
1904
    case 0x54: // I-MMU data in
1905
        {
1906
            unsigned int i;
1907

    
1908
            // Try finding an invalid entry
1909
            for (i = 0; i < 64; i++) {
1910
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1911
                    env->itlb_tag[i] = env->immuregs[6];
1912
                    env->itlb_tte[i] = val;
1913
                    return;
1914
                }
1915
            }
1916
            // Try finding an unlocked entry
1917
            for (i = 0; i < 64; i++) {
1918
                if ((env->itlb_tte[i] & 0x40) == 0) {
1919
                    env->itlb_tag[i] = env->immuregs[6];
1920
                    env->itlb_tte[i] = val;
1921
                    return;
1922
                }
1923
            }
1924
            // error state?
1925
            return;
1926
        }
1927
    case 0x55: // I-MMU data access
1928
        {
1929
            unsigned int i = (addr >> 3) & 0x3f;
1930

    
1931
            env->itlb_tag[i] = env->immuregs[6];
1932
            env->itlb_tte[i] = val;
1933
            return;
1934
        }
1935
    case 0x57: // I-MMU demap
1936
        // XXX
1937
        return;
1938
    case 0x58: // D-MMU regs
1939
        {
1940
            int reg = (addr >> 3) & 0xf;
1941
            uint64_t oldreg;
1942

    
1943
            oldreg = env->dmmuregs[reg];
1944
            switch(reg) {
1945
            case 0: // RO
1946
            case 4:
1947
                return;
1948
            case 3: // SFSR
1949
                if ((val & 1) == 0) {
1950
                    val = 0; // Clear SFSR, Fault address
1951
                    env->dmmuregs[4] = 0;
1952
                }
1953
                env->dmmuregs[reg] = val;
1954
                break;
1955
            case 1: // Primary context
1956
            case 2: // Secondary context
1957
            case 5: // TSB access
1958
            case 6: // Tag access
1959
            case 7: // Virtual Watchpoint
1960
            case 8: // Physical Watchpoint
1961
            default:
1962
                break;
1963
            }
1964
            env->dmmuregs[reg] = val;
1965
            if (oldreg != env->dmmuregs[reg]) {
1966
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1967
            }
1968
#ifdef DEBUG_MMU
1969
            dump_mmu(env);
1970
#endif
1971
            return;
1972
        }
1973
    case 0x5c: // D-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->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1980
                    env->dtlb_tag[i] = env->dmmuregs[6];
1981
                    env->dtlb_tte[i] = val;
1982
                    return;
1983
                }
1984
            }
1985
            // Try finding an unlocked entry
1986
            for (i = 0; i < 64; i++) {
1987
                if ((env->dtlb_tte[i] & 0x40) == 0) {
1988
                    env->dtlb_tag[i] = env->dmmuregs[6];
1989
                    env->dtlb_tte[i] = val;
1990
                    return;
1991
                }
1992
            }
1993
            // error state?
1994
            return;
1995
        }
1996
    case 0x5d: // D-MMU data access
1997
        {
1998
            unsigned int i = (addr >> 3) & 0x3f;
1999

    
2000
            env->dtlb_tag[i] = env->dmmuregs[6];
2001
            env->dtlb_tte[i] = val;
2002
            return;
2003
        }
2004
    case 0x5f: // D-MMU demap
2005
    case 0x49: // Interrupt data receive
2006
        // XXX
2007
        return;
2008
    case 0x51: // I-MMU 8k TSB pointer, RO
2009
    case 0x52: // I-MMU 64k TSB pointer, RO
2010
    case 0x56: // I-MMU tag read, RO
2011
    case 0x59: // D-MMU 8k TSB pointer, RO
2012
    case 0x5a: // D-MMU 64k TSB pointer, RO
2013
    case 0x5b: // D-MMU data pointer, RO
2014
    case 0x5e: // D-MMU tag read, RO
2015
    case 0x48: // Interrupt dispatch, RO
2016
    case 0x7f: // Incoming interrupt vector, RO
2017
    case 0x82: // Primary no-fault, RO
2018
    case 0x83: // Secondary no-fault, RO
2019
    case 0x8a: // Primary no-fault LE, RO
2020
    case 0x8b: // Secondary no-fault LE, RO
2021
    default:
2022
        do_unassigned_access(addr, 1, 0, 1);
2023
        return;
2024
    }
2025
}
2026
#endif /* CONFIG_USER_ONLY */
2027

    
2028
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2029
{
2030
    unsigned int i;
2031
    target_ulong val;
2032

    
2033
    helper_check_align(addr, 3);
2034
    switch (asi) {
2035
    case 0xf0: // Block load primary
2036
    case 0xf1: // Block load secondary
2037
    case 0xf8: // Block load primary LE
2038
    case 0xf9: // Block load secondary LE
2039
        if (rd & 7) {
2040
            raise_exception(TT_ILL_INSN);
2041
            return;
2042
        }
2043
        helper_check_align(addr, 0x3f);
2044
        for (i = 0; i < 16; i++) {
2045
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
2046
            addr += 4;
2047
        }
2048

    
2049
        return;
2050
    default:
2051
        break;
2052
    }
2053

    
2054
    val = helper_ld_asi(addr, asi, size, 0);
2055
    switch(size) {
2056
    default:
2057
    case 4:
2058
        *((uint32_t *)&FT0) = val;
2059
        break;
2060
    case 8:
2061
        *((int64_t *)&DT0) = val;
2062
        break;
2063
    case 16:
2064
        // XXX
2065
        break;
2066
    }
2067
}
2068

    
2069
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2070
{
2071
    unsigned int i;
2072
    target_ulong val = 0;
2073

    
2074
    helper_check_align(addr, 3);
2075
    switch (asi) {
2076
    case 0xf0: // Block store primary
2077
    case 0xf1: // Block store secondary
2078
    case 0xf8: // Block store primary LE
2079
    case 0xf9: // Block store secondary LE
2080
        if (rd & 7) {
2081
            raise_exception(TT_ILL_INSN);
2082
            return;
2083
        }
2084
        helper_check_align(addr, 0x3f);
2085
        for (i = 0; i < 16; i++) {
2086
            val = *(uint32_t *)&env->fpr[rd++];
2087
            helper_st_asi(addr, val, asi & 0x8f, 4);
2088
            addr += 4;
2089
        }
2090

    
2091
        return;
2092
    default:
2093
        break;
2094
    }
2095

    
2096
    switch(size) {
2097
    default:
2098
    case 4:
2099
        val = *((uint32_t *)&FT0);
2100
        break;
2101
    case 8:
2102
        val = *((int64_t *)&DT0);
2103
        break;
2104
    case 16:
2105
        // XXX
2106
        break;
2107
    }
2108
    helper_st_asi(addr, val, asi, size);
2109
}
2110

    
2111
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2112
                            target_ulong val2, uint32_t asi)
2113
{
2114
    target_ulong ret;
2115

    
2116
    val1 &= 0xffffffffUL;
2117
    ret = helper_ld_asi(addr, asi, 4, 0);
2118
    ret &= 0xffffffffUL;
2119
    if (val1 == ret)
2120
        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2121
    return ret;
2122
}
2123

    
2124
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2125
                             target_ulong val2, uint32_t asi)
2126
{
2127
    target_ulong ret;
2128

    
2129
    ret = helper_ld_asi(addr, asi, 8, 0);
2130
    if (val1 == ret)
2131
        helper_st_asi(addr, val2, asi, 8);
2132
    return ret;
2133
}
2134
#endif /* TARGET_SPARC64 */
2135

    
2136
#ifndef TARGET_SPARC64
2137
void helper_rett(void)
2138
{
2139
    unsigned int cwp;
2140

    
2141
    if (env->psret == 1)
2142
        raise_exception(TT_ILL_INSN);
2143

    
2144
    env->psret = 1;
2145
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2146
    if (env->wim & (1 << cwp)) {
2147
        raise_exception(TT_WIN_UNF);
2148
    }
2149
    set_cwp(cwp);
2150
    env->psrs = env->psrps;
2151
}
2152
#endif
2153

    
2154
target_ulong helper_udiv(target_ulong a, target_ulong b)
2155
{
2156
    uint64_t x0;
2157
    uint32_t x1;
2158

    
2159
    x0 = a | ((uint64_t) (env->y) << 32);
2160
    x1 = b;
2161

    
2162
    if (x1 == 0) {
2163
        raise_exception(TT_DIV_ZERO);
2164
    }
2165

    
2166
    x0 = x0 / x1;
2167
    if (x0 > 0xffffffff) {
2168
        env->cc_src2 = 1;
2169
        return 0xffffffff;
2170
    } else {
2171
        env->cc_src2 = 0;
2172
        return x0;
2173
    }
2174
}
2175

    
2176
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2177
{
2178
    int64_t x0;
2179
    int32_t x1;
2180

    
2181
    x0 = a | ((int64_t) (env->y) << 32);
2182
    x1 = b;
2183

    
2184
    if (x1 == 0) {
2185
        raise_exception(TT_DIV_ZERO);
2186
    }
2187

    
2188
    x0 = x0 / x1;
2189
    if ((int32_t) x0 != x0) {
2190
        env->cc_src2 = 1;
2191
        return x0 < 0? 0x80000000: 0x7fffffff;
2192
    } else {
2193
        env->cc_src2 = 0;
2194
        return x0;
2195
    }
2196
}
2197

    
2198
uint64_t helper_pack64(target_ulong high, target_ulong low)
2199
{
2200
    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2201
}
2202

    
2203
void helper_stdf(target_ulong addr, int mem_idx)
2204
{
2205
    helper_check_align(addr, 7);
2206
#if !defined(CONFIG_USER_ONLY)
2207
    switch (mem_idx) {
2208
    case 0:
2209
        stfq_user(addr, DT0);
2210
        break;
2211
    case 1:
2212
        stfq_kernel(addr, DT0);
2213
        break;
2214
#ifdef TARGET_SPARC64
2215
    case 2:
2216
        stfq_hypv(addr, DT0);
2217
        break;
2218
#endif
2219
    default:
2220
        break;
2221
    }
2222
#else
2223
    ABI32_MASK(addr);
2224
    stfq_raw(addr, DT0);
2225
#endif
2226
}
2227

    
2228
void helper_lddf(target_ulong addr, int mem_idx)
2229
{
2230
    helper_check_align(addr, 7);
2231
#if !defined(CONFIG_USER_ONLY)
2232
    switch (mem_idx) {
2233
    case 0:
2234
        DT0 = ldfq_user(addr);
2235
        break;
2236
    case 1:
2237
        DT0 = ldfq_kernel(addr);
2238
        break;
2239
#ifdef TARGET_SPARC64
2240
    case 2:
2241
        DT0 = ldfq_hypv(addr);
2242
        break;
2243
#endif
2244
    default:
2245
        break;
2246
    }
2247
#else
2248
    ABI32_MASK(addr);
2249
    DT0 = ldfq_raw(addr);
2250
#endif
2251
}
2252

    
2253
void helper_ldqf(target_ulong addr, int mem_idx)
2254
{
2255
    // XXX add 128 bit load
2256
    CPU_QuadU u;
2257

    
2258
    helper_check_align(addr, 7);
2259
#if !defined(CONFIG_USER_ONLY)
2260
    switch (mem_idx) {
2261
    case 0:
2262
        u.ll.upper = ldq_user(addr);
2263
        u.ll.lower = ldq_user(addr + 8);
2264
        QT0 = u.q;
2265
        break;
2266
    case 1:
2267
        u.ll.upper = ldq_kernel(addr);
2268
        u.ll.lower = ldq_kernel(addr + 8);
2269
        QT0 = u.q;
2270
        break;
2271
#ifdef TARGET_SPARC64
2272
    case 2:
2273
        u.ll.upper = ldq_hypv(addr);
2274
        u.ll.lower = ldq_hypv(addr + 8);
2275
        QT0 = u.q;
2276
        break;
2277
#endif
2278
    default:
2279
        break;
2280
    }
2281
#else
2282
    ABI32_MASK(addr);
2283
    u.ll.upper = ldq_raw(addr);
2284
    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
2285
    QT0 = u.q;
2286
#endif
2287
}
2288

    
2289
void helper_stqf(target_ulong addr, int mem_idx)
2290
{
2291
    // XXX add 128 bit store
2292
    CPU_QuadU u;
2293

    
2294
    helper_check_align(addr, 7);
2295
#if !defined(CONFIG_USER_ONLY)
2296
    switch (mem_idx) {
2297
    case 0:
2298
        u.q = QT0;
2299
        stq_user(addr, u.ll.upper);
2300
        stq_user(addr + 8, u.ll.lower);
2301
        break;
2302
    case 1:
2303
        u.q = QT0;
2304
        stq_kernel(addr, u.ll.upper);
2305
        stq_kernel(addr + 8, u.ll.lower);
2306
        break;
2307
#ifdef TARGET_SPARC64
2308
    case 2:
2309
        u.q = QT0;
2310
        stq_hypv(addr, u.ll.upper);
2311
        stq_hypv(addr + 8, u.ll.lower);
2312
        break;
2313
#endif
2314
    default:
2315
        break;
2316
    }
2317
#else
2318
    u.q = QT0;
2319
    ABI32_MASK(addr);
2320
    stq_raw(addr, u.ll.upper);
2321
    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
2322
#endif
2323
}
2324

    
2325
void helper_ldfsr(void)
2326
{
2327
    int rnd_mode;
2328

    
2329
    PUT_FSR32(env, *((uint32_t *) &FT0));
2330
    switch (env->fsr & FSR_RD_MASK) {
2331
    case FSR_RD_NEAREST:
2332
        rnd_mode = float_round_nearest_even;
2333
        break;
2334
    default:
2335
    case FSR_RD_ZERO:
2336
        rnd_mode = float_round_to_zero;
2337
        break;
2338
    case FSR_RD_POS:
2339
        rnd_mode = float_round_up;
2340
        break;
2341
    case FSR_RD_NEG:
2342
        rnd_mode = float_round_down;
2343
        break;
2344
    }
2345
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2346
}
2347

    
2348
void helper_stfsr(void)
2349
{
2350
    *((uint32_t *) &FT0) = GET_FSR32(env);
2351
}
2352

    
2353
void helper_debug(void)
2354
{
2355
    env->exception_index = EXCP_DEBUG;
2356
    cpu_loop_exit();
2357
}
2358

    
2359
#ifndef TARGET_SPARC64
2360
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2361
   handling ? */
2362
void helper_save(void)
2363
{
2364
    uint32_t cwp;
2365

    
2366
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2367
    if (env->wim & (1 << cwp)) {
2368
        raise_exception(TT_WIN_OVF);
2369
    }
2370
    set_cwp(cwp);
2371
}
2372

    
2373
void helper_restore(void)
2374
{
2375
    uint32_t cwp;
2376

    
2377
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2378
    if (env->wim & (1 << cwp)) {
2379
        raise_exception(TT_WIN_UNF);
2380
    }
2381
    set_cwp(cwp);
2382
}
2383

    
2384
void helper_wrpsr(target_ulong new_psr)
2385
{
2386
    if ((new_psr & PSR_CWP) >= NWINDOWS)
2387
        raise_exception(TT_ILL_INSN);
2388
    else
2389
        PUT_PSR(env, new_psr);
2390
}
2391

    
2392
target_ulong helper_rdpsr(void)
2393
{
2394
    return GET_PSR(env);
2395
}
2396

    
2397
#else
2398
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2399
   handling ? */
2400
void helper_save(void)
2401
{
2402
    uint32_t cwp;
2403

    
2404
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2405
    if (env->cansave == 0) {
2406
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2407
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2408
                                    ((env->wstate & 0x7) << 2)));
2409
    } else {
2410
        if (env->cleanwin - env->canrestore == 0) {
2411
            // XXX Clean windows without trap
2412
            raise_exception(TT_CLRWIN);
2413
        } else {
2414
            env->cansave--;
2415
            env->canrestore++;
2416
            set_cwp(cwp);
2417
        }
2418
    }
2419
}
2420

    
2421
void helper_restore(void)
2422
{
2423
    uint32_t cwp;
2424

    
2425
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2426
    if (env->canrestore == 0) {
2427
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2428
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2429
                                   ((env->wstate & 0x7) << 2)));
2430
    } else {
2431
        env->cansave++;
2432
        env->canrestore--;
2433
        set_cwp(cwp);
2434
    }
2435
}
2436

    
2437
void helper_flushw(void)
2438
{
2439
    if (env->cansave != NWINDOWS - 2) {
2440
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2441
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2442
                                    ((env->wstate & 0x7) << 2)));
2443
    }
2444
}
2445

    
2446
void helper_saved(void)
2447
{
2448
    env->cansave++;
2449
    if (env->otherwin == 0)
2450
        env->canrestore--;
2451
    else
2452
        env->otherwin--;
2453
}
2454

    
2455
void helper_restored(void)
2456
{
2457
    env->canrestore++;
2458
    if (env->cleanwin < NWINDOWS - 1)
2459
        env->cleanwin++;
2460
    if (env->otherwin == 0)
2461
        env->cansave--;
2462
    else
2463
        env->otherwin--;
2464
}
2465

    
2466
target_ulong helper_rdccr(void)
2467
{
2468
    return GET_CCR(env);
2469
}
2470

    
2471
void helper_wrccr(target_ulong new_ccr)
2472
{
2473
    PUT_CCR(env, new_ccr);
2474
}
2475

    
2476
// CWP handling is reversed in V9, but we still use the V8 register
2477
// order.
2478
target_ulong helper_rdcwp(void)
2479
{
2480
    return GET_CWP64(env);
2481
}
2482

    
2483
void helper_wrcwp(target_ulong new_cwp)
2484
{
2485
    PUT_CWP64(env, new_cwp);
2486
}
2487

    
2488
// This function uses non-native bit order
2489
#define GET_FIELD(X, FROM, TO)                                  \
2490
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2491

    
2492
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2493
#define GET_FIELD_SP(X, FROM, TO)               \
2494
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2495

    
2496
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2497
{
2498
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2499
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2500
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2501
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2502
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2503
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2504
        (((pixel_addr >> 55) & 1) << 4) |
2505
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2506
        GET_FIELD_SP(pixel_addr, 11, 12);
2507
}
2508

    
2509
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2510
{
2511
    uint64_t tmp;
2512

    
2513
    tmp = addr + offset;
2514
    env->gsr &= ~7ULL;
2515
    env->gsr |= tmp & 7ULL;
2516
    return tmp & ~7ULL;
2517
}
2518

    
2519
target_ulong helper_popc(target_ulong val)
2520
{
2521
    return ctpop64(val);
2522
}
2523

    
2524
static inline uint64_t *get_gregset(uint64_t pstate)
2525
{
2526
    switch (pstate) {
2527
    default:
2528
    case 0:
2529
        return env->bgregs;
2530
    case PS_AG:
2531
        return env->agregs;
2532
    case PS_MG:
2533
        return env->mgregs;
2534
    case PS_IG:
2535
        return env->igregs;
2536
    }
2537
}
2538

    
2539
static inline void change_pstate(uint64_t new_pstate)
2540
{
2541
    uint64_t pstate_regs, new_pstate_regs;
2542
    uint64_t *src, *dst;
2543

    
2544
    pstate_regs = env->pstate & 0xc01;
2545
    new_pstate_regs = new_pstate & 0xc01;
2546
    if (new_pstate_regs != pstate_regs) {
2547
        // Switch global register bank
2548
        src = get_gregset(new_pstate_regs);
2549
        dst = get_gregset(pstate_regs);
2550
        memcpy32(dst, env->gregs);
2551
        memcpy32(env->gregs, src);
2552
    }
2553
    env->pstate = new_pstate;
2554
}
2555

    
2556
void helper_wrpstate(target_ulong new_state)
2557
{
2558
    change_pstate(new_state & 0xf3f);
2559
}
2560

    
2561
void helper_done(void)
2562
{
2563
    env->tl--;
2564
    env->tsptr = &env->ts[env->tl];
2565
    env->pc = env->tsptr->tpc;
2566
    env->npc = env->tsptr->tnpc + 4;
2567
    PUT_CCR(env, env->tsptr->tstate >> 32);
2568
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2569
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2570
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2571
}
2572

    
2573
void helper_retry(void)
2574
{
2575
    env->tl--;
2576
    env->tsptr = &env->ts[env->tl];
2577
    env->pc = env->tsptr->tpc;
2578
    env->npc = env->tsptr->tnpc;
2579
    PUT_CCR(env, env->tsptr->tstate >> 32);
2580
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2581
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2582
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2583
}
2584
#endif
2585

    
2586
void set_cwp(int new_cwp)
2587
{
2588
    /* put the modified wrap registers at their proper location */
2589
    if (env->cwp == (NWINDOWS - 1))
2590
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2591
    env->cwp = new_cwp;
2592
    /* put the wrap registers at their temporary location */
2593
    if (new_cwp == (NWINDOWS - 1))
2594
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2595
    env->regwptr = env->regbase + (new_cwp * 16);
2596
    REGWPTR = env->regwptr;
2597
}
2598

    
2599
void cpu_set_cwp(CPUState *env1, int new_cwp)
2600
{
2601
    CPUState *saved_env;
2602
#ifdef reg_REGWPTR
2603
    target_ulong *saved_regwptr;
2604
#endif
2605

    
2606
    saved_env = env;
2607
#ifdef reg_REGWPTR
2608
    saved_regwptr = REGWPTR;
2609
#endif
2610
    env = env1;
2611
    set_cwp(new_cwp);
2612
    env = saved_env;
2613
#ifdef reg_REGWPTR
2614
    REGWPTR = saved_regwptr;
2615
#endif
2616
}
2617

    
2618
#ifdef TARGET_SPARC64
2619
#ifdef DEBUG_PCALL
2620
static const char * const excp_names[0x50] = {
2621
    [TT_TFAULT] = "Instruction Access Fault",
2622
    [TT_TMISS] = "Instruction Access MMU Miss",
2623
    [TT_CODE_ACCESS] = "Instruction Access Error",
2624
    [TT_ILL_INSN] = "Illegal Instruction",
2625
    [TT_PRIV_INSN] = "Privileged Instruction",
2626
    [TT_NFPU_INSN] = "FPU Disabled",
2627
    [TT_FP_EXCP] = "FPU Exception",
2628
    [TT_TOVF] = "Tag Overflow",
2629
    [TT_CLRWIN] = "Clean Windows",
2630
    [TT_DIV_ZERO] = "Division By Zero",
2631
    [TT_DFAULT] = "Data Access Fault",
2632
    [TT_DMISS] = "Data Access MMU Miss",
2633
    [TT_DATA_ACCESS] = "Data Access Error",
2634
    [TT_DPROT] = "Data Protection Error",
2635
    [TT_UNALIGNED] = "Unaligned Memory Access",
2636
    [TT_PRIV_ACT] = "Privileged Action",
2637
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2638
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2639
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2640
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2641
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2642
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2643
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2644
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2645
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2646
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2647
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2648
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2649
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2650
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2651
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2652
};
2653
#endif
2654

    
2655
void do_interrupt(int intno)
2656
{
2657
#ifdef DEBUG_PCALL
2658
    if (loglevel & CPU_LOG_INT) {
2659
        static int count;
2660
        const char *name;
2661

    
2662
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2663
            name = "Unknown";
2664
        else if (intno >= 0x100)
2665
            name = "Trap Instruction";
2666
        else if (intno >= 0xc0)
2667
            name = "Window Fill";
2668
        else if (intno >= 0x80)
2669
            name = "Window Spill";
2670
        else {
2671
            name = excp_names[intno];
2672
            if (!name)
2673
                name = "Unknown";
2674
        }
2675

    
2676
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2677
                " SP=%016" PRIx64 "\n",
2678
                count, name, intno,
2679
                env->pc,
2680
                env->npc, env->regwptr[6]);
2681
        cpu_dump_state(env, logfile, fprintf, 0);
2682
#if 0
2683
        {
2684
            int i;
2685
            uint8_t *ptr;
2686

2687
            fprintf(logfile, "       code=");
2688
            ptr = (uint8_t *)env->pc;
2689
            for(i = 0; i < 16; i++) {
2690
                fprintf(logfile, " %02x", ldub(ptr + i));
2691
            }
2692
            fprintf(logfile, "\n");
2693
        }
2694
#endif
2695
        count++;
2696
    }
2697
#endif
2698
#if !defined(CONFIG_USER_ONLY)
2699
    if (env->tl == MAXTL) {
2700
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
2701
        return;
2702
    }
2703
#endif
2704
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2705
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2706
        GET_CWP64(env);
2707
    env->tsptr->tpc = env->pc;
2708
    env->tsptr->tnpc = env->npc;
2709
    env->tsptr->tt = intno;
2710
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
2711

    
2712
    if (intno == TT_CLRWIN)
2713
        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
2714
    else if ((intno & 0x1c0) == TT_SPILL)
2715
        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
2716
    else if ((intno & 0x1c0) == TT_FILL)
2717
        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
2718
    env->tbr &= ~0x7fffULL;
2719
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2720
    if (env->tl < MAXTL - 1) {
2721
        env->tl++;
2722
    } else {
2723
        env->pstate |= PS_RED;
2724
        if (env->tl != MAXTL)
2725
            env->tl++;
2726
    }
2727
    env->tsptr = &env->ts[env->tl];
2728
    env->pc = env->tbr;
2729
    env->npc = env->pc + 4;
2730
    env->exception_index = 0;
2731
}
2732
#else
2733
#ifdef DEBUG_PCALL
2734
static const char * const excp_names[0x80] = {
2735
    [TT_TFAULT] = "Instruction Access Fault",
2736
    [TT_ILL_INSN] = "Illegal Instruction",
2737
    [TT_PRIV_INSN] = "Privileged Instruction",
2738
    [TT_NFPU_INSN] = "FPU Disabled",
2739
    [TT_WIN_OVF] = "Window Overflow",
2740
    [TT_WIN_UNF] = "Window Underflow",
2741
    [TT_UNALIGNED] = "Unaligned Memory Access",
2742
    [TT_FP_EXCP] = "FPU Exception",
2743
    [TT_DFAULT] = "Data Access Fault",
2744
    [TT_TOVF] = "Tag Overflow",
2745
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2746
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2747
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2748
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2749
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2750
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2751
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2752
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2753
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2754
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2755
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2756
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2757
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2758
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2759
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2760
    [TT_TOVF] = "Tag Overflow",
2761
    [TT_CODE_ACCESS] = "Instruction Access Error",
2762
    [TT_DATA_ACCESS] = "Data Access Error",
2763
    [TT_DIV_ZERO] = "Division By Zero",
2764
    [TT_NCP_INSN] = "Coprocessor Disabled",
2765
};
2766
#endif
2767

    
2768
void do_interrupt(int intno)
2769
{
2770
    int cwp;
2771

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

    
2777
        if (intno < 0 || intno >= 0x100)
2778
            name = "Unknown";
2779
        else if (intno >= 0x80)
2780
            name = "Trap Instruction";
2781
        else {
2782
            name = excp_names[intno];
2783
            if (!name)
2784
                name = "Unknown";
2785
        }
2786

    
2787
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2788
                count, name, intno,
2789
                env->pc,
2790
                env->npc, env->regwptr[6]);
2791
        cpu_dump_state(env, logfile, fprintf, 0);
2792
#if 0
2793
        {
2794
            int i;
2795
            uint8_t *ptr;
2796

2797
            fprintf(logfile, "       code=");
2798
            ptr = (uint8_t *)env->pc;
2799
            for(i = 0; i < 16; i++) {
2800
                fprintf(logfile, " %02x", ldub(ptr + i));
2801
            }
2802
            fprintf(logfile, "\n");
2803
        }
2804
#endif
2805
        count++;
2806
    }
2807
#endif
2808
#if !defined(CONFIG_USER_ONLY)
2809
    if (env->psret == 0) {
2810
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
2811
        return;
2812
    }
2813
#endif
2814
    env->psret = 0;
2815
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2816
    set_cwp(cwp);
2817
    env->regwptr[9] = env->pc;
2818
    env->regwptr[10] = env->npc;
2819
    env->psrps = env->psrs;
2820
    env->psrs = 1;
2821
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2822
    env->pc = env->tbr;
2823
    env->npc = env->pc + 4;
2824
    env->exception_index = 0;
2825
}
2826
#endif
2827

    
2828
#if !defined(CONFIG_USER_ONLY)
2829

    
2830
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2831
                                void *retaddr);
2832

    
2833
#define MMUSUFFIX _mmu
2834
#define ALIGNED_ONLY
2835
#ifdef __s390__
2836
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2837
#else
2838
# define GETPC() (__builtin_return_address(0))
2839
#endif
2840

    
2841
#define SHIFT 0
2842
#include "softmmu_template.h"
2843

    
2844
#define SHIFT 1
2845
#include "softmmu_template.h"
2846

    
2847
#define SHIFT 2
2848
#include "softmmu_template.h"
2849

    
2850
#define SHIFT 3
2851
#include "softmmu_template.h"
2852

    
2853
/* XXX: make it generic ? */
2854
static void cpu_restore_state2(void *retaddr)
2855
{
2856
    TranslationBlock *tb;
2857
    unsigned long pc;
2858

    
2859
    if (retaddr) {
2860
        /* now we have a real cpu fault */
2861
        pc = (unsigned long)retaddr;
2862
        tb = tb_find_pc(pc);
2863
        if (tb) {
2864
            /* the PC is inside the translated code. It means that we have
2865
               a virtual CPU fault */
2866
            cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
2867
        }
2868
    }
2869
}
2870

    
2871
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2872
                                void *retaddr)
2873
{
2874
#ifdef DEBUG_UNALIGNED
2875
    printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
2876
           "\n", addr, env->pc);
2877
#endif
2878
    cpu_restore_state2(retaddr);
2879
    raise_exception(TT_UNALIGNED);
2880
}
2881

    
2882
/* try to fill the TLB and return an exception if error. If retaddr is
2883
   NULL, it means that the function was called in C code (i.e. not
2884
   from generated code or from helper.c) */
2885
/* XXX: fix it to restore all registers */
2886
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2887
{
2888
    int ret;
2889
    CPUState *saved_env;
2890

    
2891
    /* XXX: hack to restore env in all cases, even if not called from
2892
       generated code */
2893
    saved_env = env;
2894
    env = cpu_single_env;
2895

    
2896
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2897
    if (ret) {
2898
        cpu_restore_state2(retaddr);
2899
        cpu_loop_exit();
2900
    }
2901
    env = saved_env;
2902
}
2903

    
2904
#endif
2905

    
2906
#ifndef TARGET_SPARC64
2907
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2908
                          int is_asi)
2909
{
2910
    CPUState *saved_env;
2911

    
2912
    /* XXX: hack to restore env in all cases, even if not called from
2913
       generated code */
2914
    saved_env = env;
2915
    env = cpu_single_env;
2916
#ifdef DEBUG_UNASSIGNED
2917
    if (is_asi)
2918
        printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2919
               TARGET_FMT_lx "\n",
2920
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2921
               env->pc);
2922
    else
2923
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2924
               TARGET_FMT_lx "\n",
2925
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2926
#endif
2927
    if (env->mmuregs[3]) /* Fault status register */
2928
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2929
    if (is_asi)
2930
        env->mmuregs[3] |= 1 << 16;
2931
    if (env->psrs)
2932
        env->mmuregs[3] |= 1 << 5;
2933
    if (is_exec)
2934
        env->mmuregs[3] |= 1 << 6;
2935
    if (is_write)
2936
        env->mmuregs[3] |= 1 << 7;
2937
    env->mmuregs[3] |= (5 << 2) | 2;
2938
    env->mmuregs[4] = addr; /* Fault address register */
2939
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2940
        if (is_exec)
2941
            raise_exception(TT_CODE_ACCESS);
2942
        else
2943
            raise_exception(TT_DATA_ACCESS);
2944
    }
2945
    env = saved_env;
2946
}
2947
#else
2948
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2949
                          int is_asi)
2950
{
2951
#ifdef DEBUG_UNASSIGNED
2952
    CPUState *saved_env;
2953

    
2954
    /* XXX: hack to restore env in all cases, even if not called from
2955
       generated code */
2956
    saved_env = env;
2957
    env = cpu_single_env;
2958
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2959
           addr, env->pc);
2960
    env = saved_env;
2961
#endif
2962
    if (is_exec)
2963
        raise_exception(TT_CODE_ACCESS);
2964
    else
2965
        raise_exception(TT_DATA_ACCESS);
2966
}
2967
#endif
2968