Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 2b29924f

History | View | Annotate | Download (77.9 kB)

1
#include "exec.h"
2
#include "host-utils.h"
3
#include "helper.h"
4

    
5
//#define DEBUG_PCALL
6
//#define DEBUG_MMU
7
//#define DEBUG_MXCC
8
//#define DEBUG_UNALIGNED
9
//#define DEBUG_UNASSIGNED
10
//#define DEBUG_ASI
11

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

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

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

    
33
void raise_exception(int tt)
34
{
35
    env->exception_index = tt;
36
    cpu_loop_exit();
37
}
38

    
39
void helper_trap(target_ulong nb_trap)
40
{
41
    env->exception_index = TT_TRAP + (nb_trap & 0x7f);
42
    cpu_loop_exit();
43
}
44

    
45
void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
46
{
47
    if (do_trap) {
48
        env->exception_index = TT_TRAP + (nb_trap & 0x7f);
49
        cpu_loop_exit();
50
    }
51
}
52

    
53
void helper_check_align(target_ulong addr, uint32_t align)
54
{
55
    if (addr & align)
56
        raise_exception(TT_UNALIGNED);
57
}
58

    
59
#define F_HELPER(name, p) void helper_f##name##p(void)
60

    
61
#if defined(CONFIG_USER_ONLY)
62
#define F_BINOP(name)                                           \
63
    F_HELPER(name, s)                                           \
64
    {                                                           \
65
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
66
    }                                                           \
67
    F_HELPER(name, d)                                           \
68
    {                                                           \
69
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
70
    }                                                           \
71
    F_HELPER(name, q)                                           \
72
    {                                                           \
73
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
74
    }
75
#else
76
#define F_BINOP(name)                                           \
77
    F_HELPER(name, s)                                           \
78
    {                                                           \
79
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
80
    }                                                           \
81
    F_HELPER(name, d)                                           \
82
    {                                                           \
83
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
84
    }
85
#endif
86

    
87
F_BINOP(add);
88
F_BINOP(sub);
89
F_BINOP(mul);
90
F_BINOP(div);
91
#undef F_BINOP
92

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

    
100
#if defined(CONFIG_USER_ONLY)
101
void helper_fdmulq(void)
102
{
103
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
104
                       float64_to_float128(DT1, &env->fp_status),
105
                       &env->fp_status);
106
}
107
#endif
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
#if defined(CONFIG_USER_ONLY)
121
F_HELPER(neg, q)
122
{
123
    QT0 = float128_chs(QT1);
124
}
125
#endif
126
#endif
127

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

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

    
139
#if defined(CONFIG_USER_ONLY)
140
F_HELPER(ito, q)
141
{
142
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
143
}
144
#endif
145

    
146
#ifdef TARGET_SPARC64
147
F_HELPER(xto, s)
148
{
149
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
150
}
151

    
152
F_HELPER(xto, d)
153
{
154
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
155
}
156
#if defined(CONFIG_USER_ONLY)
157
F_HELPER(xto, q)
158
{
159
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
160
}
161
#endif
162
#endif
163
#undef F_HELPER
164

    
165
/* floating point conversion */
166
void helper_fdtos(void)
167
{
168
    FT0 = float64_to_float32(DT1, &env->fp_status);
169
}
170

    
171
void helper_fstod(void)
172
{
173
    DT0 = float32_to_float64(FT1, &env->fp_status);
174
}
175

    
176
#if defined(CONFIG_USER_ONLY)
177
void helper_fqtos(void)
178
{
179
    FT0 = float128_to_float32(QT1, &env->fp_status);
180
}
181

    
182
void helper_fstoq(void)
183
{
184
    QT0 = float32_to_float128(FT1, &env->fp_status);
185
}
186

    
187
void helper_fqtod(void)
188
{
189
    DT0 = float128_to_float64(QT1, &env->fp_status);
190
}
191

    
192
void helper_fdtoq(void)
193
{
194
    QT0 = float64_to_float128(DT1, &env->fp_status);
195
}
196
#endif
197

    
198
/* Float to integer conversion.  */
199
void helper_fstoi(void)
200
{
201
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
202
}
203

    
204
void helper_fdtoi(void)
205
{
206
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
207
}
208

    
209
#if defined(CONFIG_USER_ONLY)
210
void helper_fqtoi(void)
211
{
212
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
213
}
214
#endif
215

    
216
#ifdef TARGET_SPARC64
217
void helper_fstox(void)
218
{
219
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
220
}
221

    
222
void helper_fdtox(void)
223
{
224
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
225
}
226

    
227
#if defined(CONFIG_USER_ONLY)
228
void helper_fqtox(void)
229
{
230
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
231
}
232
#endif
233

    
234
void helper_faligndata(void)
235
{
236
    uint64_t tmp;
237

    
238
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
239
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
240
    *((uint64_t *)&DT0) = tmp;
241
}
242

    
243
void helper_movl_FT0_0(void)
244
{
245
    *((uint32_t *)&FT0) = 0;
246
}
247

    
248
void helper_movl_DT0_0(void)
249
{
250
    *((uint64_t *)&DT0) = 0;
251
}
252

    
253
void helper_movl_FT0_1(void)
254
{
255
    *((uint32_t *)&FT0) = 0xffffffff;
256
}
257

    
258
void helper_movl_DT0_1(void)
259
{
260
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
261
}
262

    
263
void helper_fnot(void)
264
{
265
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
266
}
267

    
268
void helper_fnots(void)
269
{
270
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
271
}
272

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

    
278
void helper_fnors(void)
279
{
280
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
281
}
282

    
283
void helper_for(void)
284
{
285
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
286
}
287

    
288
void helper_fors(void)
289
{
290
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
291
}
292

    
293
void helper_fxor(void)
294
{
295
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
296
}
297

    
298
void helper_fxors(void)
299
{
300
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
301
}
302

    
303
void helper_fand(void)
304
{
305
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
306
}
307

    
308
void helper_fands(void)
309
{
310
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
311
}
312

    
313
void helper_fornot(void)
314
{
315
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
316
}
317

    
318
void helper_fornots(void)
319
{
320
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
321
}
322

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

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

    
333
void helper_fnand(void)
334
{
335
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 & *(uint64_t *)&DT1);
336
}
337

    
338
void helper_fnands(void)
339
{
340
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 & *(uint32_t *)&FT1);
341
}
342

    
343
void helper_fxnor(void)
344
{
345
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
346
}
347

    
348
void helper_fxnors(void)
349
{
350
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
351
}
352

    
353
#ifdef WORDS_BIGENDIAN
354
#define VIS_B64(n) b[7 - (n)]
355
#define VIS_W64(n) w[3 - (n)]
356
#define VIS_SW64(n) sw[3 - (n)]
357
#define VIS_L64(n) l[1 - (n)]
358
#define VIS_B32(n) b[3 - (n)]
359
#define VIS_W32(n) w[1 - (n)]
360
#else
361
#define VIS_B64(n) b[n]
362
#define VIS_W64(n) w[n]
363
#define VIS_SW64(n) sw[n]
364
#define VIS_L64(n) l[n]
365
#define VIS_B32(n) b[n]
366
#define VIS_W32(n) w[n]
367
#endif
368

    
369
typedef union {
370
    uint8_t b[8];
371
    uint16_t w[4];
372
    int16_t sw[4];
373
    uint32_t l[2];
374
    float64 d;
375
} vis64;
376

    
377
typedef union {
378
    uint8_t b[4];
379
    uint16_t w[2];
380
    uint32_t l;
381
    float32 f;
382
} vis32;
383

    
384
void helper_fpmerge(void)
385
{
386
    vis64 s, d;
387

    
388
    s.d = DT0;
389
    d.d = DT1;
390

    
391
    // Reverse calculation order to handle overlap
392
    d.VIS_B64(7) = s.VIS_B64(3);
393
    d.VIS_B64(6) = d.VIS_B64(3);
394
    d.VIS_B64(5) = s.VIS_B64(2);
395
    d.VIS_B64(4) = d.VIS_B64(2);
396
    d.VIS_B64(3) = s.VIS_B64(1);
397
    d.VIS_B64(2) = d.VIS_B64(1);
398
    d.VIS_B64(1) = s.VIS_B64(0);
399
    //d.VIS_B64(0) = d.VIS_B64(0);
400

    
401
    DT0 = d.d;
402
}
403

    
404
void helper_fmul8x16(void)
405
{
406
    vis64 s, d;
407
    uint32_t tmp;
408

    
409
    s.d = DT0;
410
    d.d = DT1;
411

    
412
#define PMUL(r)                                                 \
413
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
414
    if ((tmp & 0xff) > 0x7f)                                    \
415
        tmp += 0x100;                                           \
416
    d.VIS_W64(r) = tmp >> 8;
417

    
418
    PMUL(0);
419
    PMUL(1);
420
    PMUL(2);
421
    PMUL(3);
422
#undef PMUL
423

    
424
    DT0 = d.d;
425
}
426

    
427
void helper_fmul8x16al(void)
428
{
429
    vis64 s, d;
430
    uint32_t tmp;
431

    
432
    s.d = DT0;
433
    d.d = DT1;
434

    
435
#define PMUL(r)                                                 \
436
    tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
437
    if ((tmp & 0xff) > 0x7f)                                    \
438
        tmp += 0x100;                                           \
439
    d.VIS_W64(r) = tmp >> 8;
440

    
441
    PMUL(0);
442
    PMUL(1);
443
    PMUL(2);
444
    PMUL(3);
445
#undef PMUL
446

    
447
    DT0 = d.d;
448
}
449

    
450
void helper_fmul8x16au(void)
451
{
452
    vis64 s, d;
453
    uint32_t tmp;
454

    
455
    s.d = DT0;
456
    d.d = DT1;
457

    
458
#define PMUL(r)                                                 \
459
    tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
460
    if ((tmp & 0xff) > 0x7f)                                    \
461
        tmp += 0x100;                                           \
462
    d.VIS_W64(r) = tmp >> 8;
463

    
464
    PMUL(0);
465
    PMUL(1);
466
    PMUL(2);
467
    PMUL(3);
468
#undef PMUL
469

    
470
    DT0 = d.d;
471
}
472

    
473
void helper_fmul8sux16(void)
474
{
475
    vis64 s, d;
476
    uint32_t tmp;
477

    
478
    s.d = DT0;
479
    d.d = DT1;
480

    
481
#define PMUL(r)                                                         \
482
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
483
    if ((tmp & 0xff) > 0x7f)                                            \
484
        tmp += 0x100;                                                   \
485
    d.VIS_W64(r) = tmp >> 8;
486

    
487
    PMUL(0);
488
    PMUL(1);
489
    PMUL(2);
490
    PMUL(3);
491
#undef PMUL
492

    
493
    DT0 = d.d;
494
}
495

    
496
void helper_fmul8ulx16(void)
497
{
498
    vis64 s, d;
499
    uint32_t tmp;
500

    
501
    s.d = DT0;
502
    d.d = DT1;
503

    
504
#define PMUL(r)                                                         \
505
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
506
    if ((tmp & 0xff) > 0x7f)                                            \
507
        tmp += 0x100;                                                   \
508
    d.VIS_W64(r) = tmp >> 8;
509

    
510
    PMUL(0);
511
    PMUL(1);
512
    PMUL(2);
513
    PMUL(3);
514
#undef PMUL
515

    
516
    DT0 = d.d;
517
}
518

    
519
void helper_fmuld8sux16(void)
520
{
521
    vis64 s, d;
522
    uint32_t tmp;
523

    
524
    s.d = DT0;
525
    d.d = DT1;
526

    
527
#define PMUL(r)                                                         \
528
    tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
529
    if ((tmp & 0xff) > 0x7f)                                            \
530
        tmp += 0x100;                                                   \
531
    d.VIS_L64(r) = tmp;
532

    
533
    // Reverse calculation order to handle overlap
534
    PMUL(1);
535
    PMUL(0);
536
#undef PMUL
537

    
538
    DT0 = d.d;
539
}
540

    
541
void helper_fmuld8ulx16(void)
542
{
543
    vis64 s, d;
544
    uint32_t tmp;
545

    
546
    s.d = DT0;
547
    d.d = DT1;
548

    
549
#define PMUL(r)                                                         \
550
    tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
551
    if ((tmp & 0xff) > 0x7f)                                            \
552
        tmp += 0x100;                                                   \
553
    d.VIS_L64(r) = tmp;
554

    
555
    // Reverse calculation order to handle overlap
556
    PMUL(1);
557
    PMUL(0);
558
#undef PMUL
559

    
560
    DT0 = d.d;
561
}
562

    
563
void helper_fexpand(void)
564
{
565
    vis32 s;
566
    vis64 d;
567

    
568
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
569
    d.d = DT1;
570
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
571
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
572
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
573
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
574

    
575
    DT0 = d.d;
576
}
577

    
578
#define VIS_HELPER(name, F)                             \
579
    void name##16(void)                                 \
580
    {                                                   \
581
        vis64 s, d;                                     \
582
                                                        \
583
        s.d = DT0;                                      \
584
        d.d = DT1;                                      \
585
                                                        \
586
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
587
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
588
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
589
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
590
                                                        \
591
        DT0 = d.d;                                      \
592
    }                                                   \
593
                                                        \
594
    void name##16s(void)                                \
595
    {                                                   \
596
        vis32 s, d;                                     \
597
                                                        \
598
        s.f = FT0;                                      \
599
        d.f = FT1;                                      \
600
                                                        \
601
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
602
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
603
                                                        \
604
        FT0 = d.f;                                      \
605
    }                                                   \
606
                                                        \
607
    void name##32(void)                                 \
608
    {                                                   \
609
        vis64 s, d;                                     \
610
                                                        \
611
        s.d = DT0;                                      \
612
        d.d = DT1;                                      \
613
                                                        \
614
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
615
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
616
                                                        \
617
        DT0 = d.d;                                      \
618
    }                                                   \
619
                                                        \
620
    void name##32s(void)                                \
621
    {                                                   \
622
        vis32 s, d;                                     \
623
                                                        \
624
        s.f = FT0;                                      \
625
        d.f = FT1;                                      \
626
                                                        \
627
        d.l = F(d.l, s.l);                              \
628
                                                        \
629
        FT0 = d.f;                                      \
630
    }
631

    
632
#define FADD(a, b) ((a) + (b))
633
#define FSUB(a, b) ((a) - (b))
634
VIS_HELPER(helper_fpadd, FADD)
635
VIS_HELPER(helper_fpsub, FSUB)
636

    
637
#define VIS_CMPHELPER(name, F)                                        \
638
    void name##16(void)                                           \
639
    {                                                             \
640
        vis64 s, d;                                               \
641
                                                                  \
642
        s.d = DT0;                                                \
643
        d.d = DT1;                                                \
644
                                                                  \
645
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
646
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
647
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
648
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
649
                                                                  \
650
        DT0 = d.d;                                                \
651
    }                                                             \
652
                                                                  \
653
    void name##32(void)                                           \
654
    {                                                             \
655
        vis64 s, d;                                               \
656
                                                                  \
657
        s.d = DT0;                                                \
658
        d.d = DT1;                                                \
659
                                                                  \
660
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
661
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
662
                                                                  \
663
        DT0 = d.d;                                                \
664
    }
665

    
666
#define FCMPGT(a, b) ((a) > (b))
667
#define FCMPEQ(a, b) ((a) == (b))
668
#define FCMPLE(a, b) ((a) <= (b))
669
#define FCMPNE(a, b) ((a) != (b))
670

    
671
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
672
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
673
VIS_CMPHELPER(helper_fcmple, FCMPLE)
674
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
675
#endif
676

    
677
void helper_check_ieee_exceptions(void)
678
{
679
    target_ulong status;
680

    
681
    status = get_float_exception_flags(&env->fp_status);
682
    if (status) {
683
        /* Copy IEEE 754 flags into FSR */
684
        if (status & float_flag_invalid)
685
            env->fsr |= FSR_NVC;
686
        if (status & float_flag_overflow)
687
            env->fsr |= FSR_OFC;
688
        if (status & float_flag_underflow)
689
            env->fsr |= FSR_UFC;
690
        if (status & float_flag_divbyzero)
691
            env->fsr |= FSR_DZC;
692
        if (status & float_flag_inexact)
693
            env->fsr |= FSR_NXC;
694

    
695
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
696
            /* Unmasked exception, generate a trap */
697
            env->fsr |= FSR_FTT_IEEE_EXCP;
698
            raise_exception(TT_FP_EXCP);
699
        } else {
700
            /* Accumulate exceptions */
701
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
702
        }
703
    }
704
}
705

    
706
void helper_clear_float_exceptions(void)
707
{
708
    set_float_exception_flags(0, &env->fp_status);
709
}
710

    
711
void helper_fabss(void)
712
{
713
    FT0 = float32_abs(FT1);
714
}
715

    
716
#ifdef TARGET_SPARC64
717
void helper_fabsd(void)
718
{
719
    DT0 = float64_abs(DT1);
720
}
721

    
722
#if defined(CONFIG_USER_ONLY)
723
void helper_fabsq(void)
724
{
725
    QT0 = float128_abs(QT1);
726
}
727
#endif
728
#endif
729

    
730
void helper_fsqrts(void)
731
{
732
    FT0 = float32_sqrt(FT1, &env->fp_status);
733
}
734

    
735
void helper_fsqrtd(void)
736
{
737
    DT0 = float64_sqrt(DT1, &env->fp_status);
738
}
739

    
740
#if defined(CONFIG_USER_ONLY)
741
void helper_fsqrtq(void)
742
{
743
    QT0 = float128_sqrt(QT1, &env->fp_status);
744
}
745
#endif
746

    
747
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
748
    void glue(helper_, name) (void)                                     \
749
    {                                                                   \
750
        target_ulong new_fsr;                                           \
751
                                                                        \
752
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
753
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
754
        case float_relation_unordered:                                  \
755
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
756
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
757
                env->fsr |= new_fsr;                                    \
758
                env->fsr |= FSR_NVC;                                    \
759
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
760
                raise_exception(TT_FP_EXCP);                            \
761
            } else {                                                    \
762
                env->fsr |= FSR_NVA;                                    \
763
            }                                                           \
764
            break;                                                      \
765
        case float_relation_less:                                       \
766
            new_fsr = FSR_FCC0 << FS;                                   \
767
            break;                                                      \
768
        case float_relation_greater:                                    \
769
            new_fsr = FSR_FCC1 << FS;                                   \
770
            break;                                                      \
771
        default:                                                        \
772
            new_fsr = 0;                                                \
773
            break;                                                      \
774
        }                                                               \
775
        env->fsr |= new_fsr;                                            \
776
    }
777

    
778
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
779
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
780

    
781
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
782
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
783

    
784
#ifdef CONFIG_USER_ONLY
785
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
786
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
787
#endif
788

    
789
#ifdef TARGET_SPARC64
790
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
791
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
792

    
793
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
794
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
795

    
796
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
797
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
798

    
799
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
800
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
801

    
802
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
803
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
804

    
805
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
806
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
807
#ifdef CONFIG_USER_ONLY
808
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
809
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
810
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
811
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
812
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
813
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
814
#endif
815
#endif
816

    
817
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
818
static void dump_mxcc(CPUState *env)
819
{
820
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
821
        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
822
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
823
           "          %016llx %016llx %016llx %016llx\n",
824
        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
825
        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
826
}
827
#endif
828

    
829
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
830
    && defined(DEBUG_ASI)
831
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
832
                     uint64_t r1)
833
{
834
    switch (size)
835
    {
836
    case 1:
837
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
838
                    addr, asi, r1 & 0xff);
839
        break;
840
    case 2:
841
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
842
                    addr, asi, r1 & 0xffff);
843
        break;
844
    case 4:
845
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
846
                    addr, asi, r1 & 0xffffffff);
847
        break;
848
    case 8:
849
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
850
                    addr, asi, r1);
851
        break;
852
    }
853
}
854
#endif
855

    
856
#ifndef TARGET_SPARC64
857
#ifndef CONFIG_USER_ONLY
858
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
859
{
860
    uint64_t ret = 0;
861
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
862
    uint32_t last_addr = addr;
863
#endif
864

    
865
    switch (asi) {
866
    case 2: /* SuperSparc MXCC registers */
867
        switch (addr) {
868
        case 0x01c00a00: /* MXCC control register */
869
            if (size == 8)
870
                ret = env->mxccregs[3];
871
            else
872
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
873
            break;
874
        case 0x01c00a04: /* MXCC control register */
875
            if (size == 4)
876
                ret = env->mxccregs[3];
877
            else
878
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
879
            break;
880
        case 0x01c00c00: /* Module reset register */
881
            if (size == 8) {
882
                ret = env->mxccregs[5];
883
                // should we do something here?
884
            } else
885
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
886
            break;
887
        case 0x01c00f00: /* MBus port address register */
888
            if (size == 8)
889
                ret = env->mxccregs[7];
890
            else
891
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
892
            break;
893
        default:
894
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
895
            break;
896
        }
897
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
898
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
899
#ifdef DEBUG_MXCC
900
        dump_mxcc(env);
901
#endif
902
        break;
903
    case 3: /* MMU probe */
904
        {
905
            int mmulev;
906

    
907
            mmulev = (addr >> 8) & 15;
908
            if (mmulev > 4)
909
                ret = 0;
910
            else
911
                ret = mmu_probe(env, addr, mmulev);
912
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
913
                        addr, mmulev, ret);
914
        }
915
        break;
916
    case 4: /* read MMU regs */
917
        {
918
            int reg = (addr >> 8) & 0x1f;
919

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

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

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

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

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

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

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

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

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

    
1368
    switch (asi) {
1369
    case 0x80: // Primary
1370
    case 0x82: // Primary no-fault
1371
    case 0x88: // Primary LE
1372
    case 0x8a: // Primary no-fault LE
1373
        {
1374
            switch(size) {
1375
            case 1:
1376
                ret = ldub_raw(addr);
1377
                break;
1378
            case 2:
1379
                ret = lduw_raw(addr & ~1);
1380
                break;
1381
            case 4:
1382
                ret = ldl_raw(addr & ~3);
1383
                break;
1384
            default:
1385
            case 8:
1386
                ret = ldq_raw(addr & ~7);
1387
                break;
1388
            }
1389
        }
1390
        break;
1391
    case 0x81: // Secondary
1392
    case 0x83: // Secondary no-fault
1393
    case 0x89: // Secondary LE
1394
    case 0x8b: // Secondary no-fault LE
1395
        // XXX
1396
        break;
1397
    default:
1398
        break;
1399
    }
1400

    
1401
    /* Convert from little endian */
1402
    switch (asi) {
1403
    case 0x88: // Primary LE
1404
    case 0x89: // Secondary LE
1405
    case 0x8a: // Primary no-fault LE
1406
    case 0x8b: // Secondary no-fault LE
1407
        switch(size) {
1408
        case 2:
1409
            ret = bswap16(ret);
1410
            break;
1411
        case 4:
1412
            ret = bswap32(ret);
1413
            break;
1414
        case 8:
1415
            ret = bswap64(ret);
1416
            break;
1417
        default:
1418
            break;
1419
        }
1420
    default:
1421
        break;
1422
    }
1423

    
1424
    /* Convert to signed number */
1425
    if (sign) {
1426
        switch(size) {
1427
        case 1:
1428
            ret = (int8_t) ret;
1429
            break;
1430
        case 2:
1431
            ret = (int16_t) ret;
1432
            break;
1433
        case 4:
1434
            ret = (int32_t) ret;
1435
            break;
1436
        default:
1437
            break;
1438
        }
1439
    }
1440
#ifdef DEBUG_ASI
1441
    dump_asi("read ", last_addr, asi, size, ret);
1442
#endif
1443
    return ret;
1444
}
1445

    
1446
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1447
{
1448
#ifdef DEBUG_ASI
1449
    dump_asi("write", addr, asi, size, val);
1450
#endif
1451
    if (asi < 0x80)
1452
        raise_exception(TT_PRIV_ACT);
1453

    
1454
    /* Convert to little endian */
1455
    switch (asi) {
1456
    case 0x88: // Primary LE
1457
    case 0x89: // Secondary LE
1458
        switch(size) {
1459
        case 2:
1460
            addr = bswap16(addr);
1461
            break;
1462
        case 4:
1463
            addr = bswap32(addr);
1464
            break;
1465
        case 8:
1466
            addr = bswap64(addr);
1467
            break;
1468
        default:
1469
            break;
1470
        }
1471
    default:
1472
        break;
1473
    }
1474

    
1475
    switch(asi) {
1476
    case 0x80: // Primary
1477
    case 0x88: // Primary LE
1478
        {
1479
            switch(size) {
1480
            case 1:
1481
                stb_raw(addr, val);
1482
                break;
1483
            case 2:
1484
                stw_raw(addr & ~1, val);
1485
                break;
1486
            case 4:
1487
                stl_raw(addr & ~3, val);
1488
                break;
1489
            case 8:
1490
            default:
1491
                stq_raw(addr & ~7, val);
1492
                break;
1493
            }
1494
        }
1495
        break;
1496
    case 0x81: // Secondary
1497
    case 0x89: // Secondary LE
1498
        // XXX
1499
        return;
1500

    
1501
    case 0x82: // Primary no-fault, RO
1502
    case 0x83: // Secondary no-fault, RO
1503
    case 0x8a: // Primary no-fault LE, RO
1504
    case 0x8b: // Secondary no-fault LE, RO
1505
    default:
1506
        do_unassigned_access(addr, 1, 0, 1);
1507
        return;
1508
    }
1509
}
1510

    
1511
#else /* CONFIG_USER_ONLY */
1512

    
1513
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1514
{
1515
    uint64_t ret = 0;
1516
#if defined(DEBUG_ASI)
1517
    target_ulong last_addr = addr;
1518
#endif
1519

    
1520
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1521
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1522
        raise_exception(TT_PRIV_ACT);
1523

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

    
1625
            ret = env->immuregs[reg];
1626
            break;
1627
        }
1628
    case 0x51: // I-MMU 8k TSB pointer
1629
    case 0x52: // I-MMU 64k TSB pointer
1630
    case 0x55: // I-MMU data access
1631
        // XXX
1632
        break;
1633
    case 0x56: // I-MMU tag read
1634
        {
1635
            unsigned int i;
1636

    
1637
            for (i = 0; i < 64; i++) {
1638
                // Valid, ctx match, vaddr match
1639
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1640
                    env->itlb_tag[i] == addr) {
1641
                    ret = env->itlb_tag[i];
1642
                    break;
1643
                }
1644
            }
1645
            break;
1646
        }
1647
    case 0x58: // D-MMU regs
1648
        {
1649
            int reg = (addr >> 3) & 0xf;
1650

    
1651
            ret = env->dmmuregs[reg];
1652
            break;
1653
        }
1654
    case 0x5e: // D-MMU tag read
1655
        {
1656
            unsigned int i;
1657

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

    
1688
    /* Convert from little endian */
1689
    switch (asi) {
1690
    case 0x0c: // Nucleus Little Endian (LE)
1691
    case 0x18: // As if user primary LE
1692
    case 0x19: // As if user secondary LE
1693
    case 0x1c: // Bypass LE
1694
    case 0x1d: // Bypass, non-cacheable LE
1695
    case 0x88: // Primary LE
1696
    case 0x89: // Secondary LE
1697
    case 0x8a: // Primary no-fault LE
1698
    case 0x8b: // Secondary no-fault LE
1699
        switch(size) {
1700
        case 2:
1701
            ret = bswap16(ret);
1702
            break;
1703
        case 4:
1704
            ret = bswap32(ret);
1705
            break;
1706
        case 8:
1707
            ret = bswap64(ret);
1708
            break;
1709
        default:
1710
            break;
1711
        }
1712
    default:
1713
        break;
1714
    }
1715

    
1716
    /* Convert to signed number */
1717
    if (sign) {
1718
        switch(size) {
1719
        case 1:
1720
            ret = (int8_t) ret;
1721
            break;
1722
        case 2:
1723
            ret = (int16_t) ret;
1724
            break;
1725
        case 4:
1726
            ret = (int32_t) ret;
1727
            break;
1728
        default:
1729
            break;
1730
        }
1731
    }
1732
#ifdef DEBUG_ASI
1733
    dump_asi("read ", last_addr, asi, size, ret);
1734
#endif
1735
    return ret;
1736
}
1737

    
1738
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1739
{
1740
#ifdef DEBUG_ASI
1741
    dump_asi("write", addr, asi, size, val);
1742
#endif
1743
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1744
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1745
        raise_exception(TT_PRIV_ACT);
1746

    
1747
    /* Convert to little endian */
1748
    switch (asi) {
1749
    case 0x0c: // Nucleus Little Endian (LE)
1750
    case 0x18: // As if user primary LE
1751
    case 0x19: // As if user secondary LE
1752
    case 0x1c: // Bypass LE
1753
    case 0x1d: // Bypass, non-cacheable LE
1754
    case 0x88: // Primary LE
1755
    case 0x89: // Secondary LE
1756
        switch(size) {
1757
        case 2:
1758
            addr = bswap16(addr);
1759
            break;
1760
        case 4:
1761
            addr = bswap32(addr);
1762
            break;
1763
        case 8:
1764
            addr = bswap64(addr);
1765
            break;
1766
        default:
1767
            break;
1768
        }
1769
    default:
1770
        break;
1771
    }
1772

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

    
1867
            oldreg = env->lsu;
1868
            env->lsu = val & (DMMU_E | IMMU_E);
1869
            // Mappings generated during D/I MMU disabled mode are
1870
            // invalid in normal mode
1871
            if (oldreg != env->lsu) {
1872
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1873
#ifdef DEBUG_MMU
1874
                dump_mmu(env);
1875
#endif
1876
                tlb_flush(env, 1);
1877
            }
1878
            return;
1879
        }
1880
    case 0x50: // I-MMU regs
1881
        {
1882
            int reg = (addr >> 3) & 0xf;
1883
            uint64_t oldreg;
1884

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

    
1917
            // Try finding an invalid entry
1918
            for (i = 0; i < 64; i++) {
1919
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1920
                    env->itlb_tag[i] = env->immuregs[6];
1921
                    env->itlb_tte[i] = val;
1922
                    return;
1923
                }
1924
            }
1925
            // Try finding an unlocked entry
1926
            for (i = 0; i < 64; i++) {
1927
                if ((env->itlb_tte[i] & 0x40) == 0) {
1928
                    env->itlb_tag[i] = env->immuregs[6];
1929
                    env->itlb_tte[i] = val;
1930
                    return;
1931
                }
1932
            }
1933
            // error state?
1934
            return;
1935
        }
1936
    case 0x55: // I-MMU data access
1937
        {
1938
            unsigned int i = (addr >> 3) & 0x3f;
1939

    
1940
            env->itlb_tag[i] = env->immuregs[6];
1941
            env->itlb_tte[i] = val;
1942
            return;
1943
        }
1944
    case 0x57: // I-MMU demap
1945
        // XXX
1946
        return;
1947
    case 0x58: // D-MMU regs
1948
        {
1949
            int reg = (addr >> 3) & 0xf;
1950
            uint64_t oldreg;
1951

    
1952
            oldreg = env->dmmuregs[reg];
1953
            switch(reg) {
1954
            case 0: // RO
1955
            case 4:
1956
                return;
1957
            case 3: // SFSR
1958
                if ((val & 1) == 0) {
1959
                    val = 0; // Clear SFSR, Fault address
1960
                    env->dmmuregs[4] = 0;
1961
                }
1962
                env->dmmuregs[reg] = val;
1963
                break;
1964
            case 1: // Primary context
1965
            case 2: // Secondary context
1966
            case 5: // TSB access
1967
            case 6: // Tag access
1968
            case 7: // Virtual Watchpoint
1969
            case 8: // Physical Watchpoint
1970
            default:
1971
                break;
1972
            }
1973
            env->dmmuregs[reg] = val;
1974
            if (oldreg != env->dmmuregs[reg]) {
1975
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1976
            }
1977
#ifdef DEBUG_MMU
1978
            dump_mmu(env);
1979
#endif
1980
            return;
1981
        }
1982
    case 0x5c: // D-MMU data in
1983
        {
1984
            unsigned int i;
1985

    
1986
            // Try finding an invalid entry
1987
            for (i = 0; i < 64; i++) {
1988
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1989
                    env->dtlb_tag[i] = env->dmmuregs[6];
1990
                    env->dtlb_tte[i] = val;
1991
                    return;
1992
                }
1993
            }
1994
            // Try finding an unlocked entry
1995
            for (i = 0; i < 64; i++) {
1996
                if ((env->dtlb_tte[i] & 0x40) == 0) {
1997
                    env->dtlb_tag[i] = env->dmmuregs[6];
1998
                    env->dtlb_tte[i] = val;
1999
                    return;
2000
                }
2001
            }
2002
            // error state?
2003
            return;
2004
        }
2005
    case 0x5d: // D-MMU data access
2006
        {
2007
            unsigned int i = (addr >> 3) & 0x3f;
2008

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

    
2037
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2038
{
2039
    unsigned int i;
2040
    target_ulong val;
2041

    
2042
    switch (asi) {
2043
    case 0xf0: // Block load primary
2044
    case 0xf1: // Block load secondary
2045
    case 0xf8: // Block load primary LE
2046
    case 0xf9: // Block load secondary LE
2047
        if (rd & 7) {
2048
            raise_exception(TT_ILL_INSN);
2049
            return;
2050
        }
2051
        if (addr & 0x3f) {
2052
            raise_exception(TT_UNALIGNED);
2053
            return;
2054
        }
2055
        for (i = 0; i < 16; i++) {
2056
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
2057
            addr += 4;
2058
        }
2059

    
2060
        return;
2061
    default:
2062
        break;
2063
    }
2064

    
2065
    val = helper_ld_asi(addr, asi, size, 0);
2066
    switch(size) {
2067
    default:
2068
    case 4:
2069
        *((uint32_t *)&FT0) = val;
2070
        break;
2071
    case 8:
2072
        *((int64_t *)&DT0) = val;
2073
        break;
2074
#if defined(CONFIG_USER_ONLY)
2075
    case 16:
2076
        // XXX
2077
        break;
2078
#endif
2079
    }
2080
}
2081

    
2082
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2083
{
2084
    unsigned int i;
2085
    target_ulong val = 0;
2086

    
2087
    switch (asi) {
2088
    case 0xf0: // Block store primary
2089
    case 0xf1: // Block store secondary
2090
    case 0xf8: // Block store primary LE
2091
    case 0xf9: // Block store secondary LE
2092
        if (rd & 7) {
2093
            raise_exception(TT_ILL_INSN);
2094
            return;
2095
        }
2096
        if (addr & 0x3f) {
2097
            raise_exception(TT_UNALIGNED);
2098
            return;
2099
        }
2100
        for (i = 0; i < 16; i++) {
2101
            val = *(uint32_t *)&env->fpr[rd++];
2102
            helper_st_asi(addr, val, asi & 0x8f, 4);
2103
            addr += 4;
2104
        }
2105

    
2106
        return;
2107
    default:
2108
        break;
2109
    }
2110

    
2111
    switch(size) {
2112
    default:
2113
    case 4:
2114
        val = *((uint32_t *)&FT0);
2115
        break;
2116
    case 8:
2117
        val = *((int64_t *)&DT0);
2118
        break;
2119
#if defined(CONFIG_USER_ONLY)
2120
    case 16:
2121
        // XXX
2122
        break;
2123
#endif
2124
    }
2125
    helper_st_asi(addr, val, asi, size);
2126
}
2127

    
2128
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2129
                            target_ulong val2, uint32_t asi)
2130
{
2131
    target_ulong ret;
2132

    
2133
    val1 &= 0xffffffffUL;
2134
    ret = helper_ld_asi(addr, asi, 4, 0);
2135
    ret &= 0xffffffffUL;
2136
    if (val1 == ret)
2137
        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2138
    return ret;
2139
}
2140

    
2141
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2142
                             target_ulong val2, uint32_t asi)
2143
{
2144
    target_ulong ret;
2145

    
2146
    ret = helper_ld_asi(addr, asi, 8, 0);
2147
    if (val1 == ret)
2148
        helper_st_asi(addr, val2, asi, 8);
2149
    return ret;
2150
}
2151
#endif /* TARGET_SPARC64 */
2152

    
2153
#ifndef TARGET_SPARC64
2154
void helper_rett(void)
2155
{
2156
    unsigned int cwp;
2157

    
2158
    if (env->psret == 1)
2159
        raise_exception(TT_ILL_INSN);
2160

    
2161
    env->psret = 1;
2162
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2163
    if (env->wim & (1 << cwp)) {
2164
        raise_exception(TT_WIN_UNF);
2165
    }
2166
    set_cwp(cwp);
2167
    env->psrs = env->psrps;
2168
}
2169
#endif
2170

    
2171
target_ulong helper_udiv(target_ulong a, target_ulong b)
2172
{
2173
    uint64_t x0;
2174
    uint32_t x1;
2175

    
2176
    x0 = a | ((uint64_t) (env->y) << 32);
2177
    x1 = b;
2178

    
2179
    if (x1 == 0) {
2180
        raise_exception(TT_DIV_ZERO);
2181
    }
2182

    
2183
    x0 = x0 / x1;
2184
    if (x0 > 0xffffffff) {
2185
        env->cc_src2 = 1;
2186
        return 0xffffffff;
2187
    } else {
2188
        env->cc_src2 = 0;
2189
        return x0;
2190
    }
2191
}
2192

    
2193
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2194
{
2195
    int64_t x0;
2196
    int32_t x1;
2197

    
2198
    x0 = a | ((int64_t) (env->y) << 32);
2199
    x1 = b;
2200

    
2201
    if (x1 == 0) {
2202
        raise_exception(TT_DIV_ZERO);
2203
    }
2204

    
2205
    x0 = x0 / x1;
2206
    if ((int32_t) x0 != x0) {
2207
        env->cc_src2 = 1;
2208
        return x0 < 0? 0x80000000: 0x7fffffff;
2209
    } else {
2210
        env->cc_src2 = 0;
2211
        return x0;
2212
    }
2213
}
2214

    
2215
uint64_t helper_pack64(target_ulong high, target_ulong low)
2216
{
2217
    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2218
}
2219

    
2220
void helper_ldfsr(void)
2221
{
2222
    int rnd_mode;
2223

    
2224
    PUT_FSR32(env, *((uint32_t *) &FT0));
2225
    switch (env->fsr & FSR_RD_MASK) {
2226
    case FSR_RD_NEAREST:
2227
        rnd_mode = float_round_nearest_even;
2228
        break;
2229
    default:
2230
    case FSR_RD_ZERO:
2231
        rnd_mode = float_round_to_zero;
2232
        break;
2233
    case FSR_RD_POS:
2234
        rnd_mode = float_round_up;
2235
        break;
2236
    case FSR_RD_NEG:
2237
        rnd_mode = float_round_down;
2238
        break;
2239
    }
2240
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2241
}
2242

    
2243
void helper_stfsr(void)
2244
{
2245
    *((uint32_t *) &FT0) = GET_FSR32(env);
2246
}
2247

    
2248
void helper_debug(void)
2249
{
2250
    env->exception_index = EXCP_DEBUG;
2251
    cpu_loop_exit();
2252
}
2253

    
2254
#ifndef TARGET_SPARC64
2255
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2256
   handling ? */
2257
void helper_save(void)
2258
{
2259
    uint32_t cwp;
2260

    
2261
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2262
    if (env->wim & (1 << cwp)) {
2263
        raise_exception(TT_WIN_OVF);
2264
    }
2265
    set_cwp(cwp);
2266
}
2267

    
2268
void helper_restore(void)
2269
{
2270
    uint32_t cwp;
2271

    
2272
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2273
    if (env->wim & (1 << cwp)) {
2274
        raise_exception(TT_WIN_UNF);
2275
    }
2276
    set_cwp(cwp);
2277
}
2278

    
2279
void helper_wrpsr(target_ulong new_psr)
2280
{
2281
    if ((new_psr & PSR_CWP) >= NWINDOWS)
2282
        raise_exception(TT_ILL_INSN);
2283
    else
2284
        PUT_PSR(env, new_psr);
2285
}
2286

    
2287
target_ulong helper_rdpsr(void)
2288
{
2289
    return GET_PSR(env);
2290
}
2291

    
2292
#else
2293
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2294
   handling ? */
2295
void helper_save(void)
2296
{
2297
    uint32_t cwp;
2298

    
2299
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2300
    if (env->cansave == 0) {
2301
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2302
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2303
                                    ((env->wstate & 0x7) << 2)));
2304
    } else {
2305
        if (env->cleanwin - env->canrestore == 0) {
2306
            // XXX Clean windows without trap
2307
            raise_exception(TT_CLRWIN);
2308
        } else {
2309
            env->cansave--;
2310
            env->canrestore++;
2311
            set_cwp(cwp);
2312
        }
2313
    }
2314
}
2315

    
2316
void helper_restore(void)
2317
{
2318
    uint32_t cwp;
2319

    
2320
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2321
    if (env->canrestore == 0) {
2322
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2323
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2324
                                   ((env->wstate & 0x7) << 2)));
2325
    } else {
2326
        env->cansave++;
2327
        env->canrestore--;
2328
        set_cwp(cwp);
2329
    }
2330
}
2331

    
2332
void helper_flushw(void)
2333
{
2334
    if (env->cansave != NWINDOWS - 2) {
2335
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2336
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2337
                                    ((env->wstate & 0x7) << 2)));
2338
    }
2339
}
2340

    
2341
void helper_saved(void)
2342
{
2343
    env->cansave++;
2344
    if (env->otherwin == 0)
2345
        env->canrestore--;
2346
    else
2347
        env->otherwin--;
2348
}
2349

    
2350
void helper_restored(void)
2351
{
2352
    env->canrestore++;
2353
    if (env->cleanwin < NWINDOWS - 1)
2354
        env->cleanwin++;
2355
    if (env->otherwin == 0)
2356
        env->cansave--;
2357
    else
2358
        env->otherwin--;
2359
}
2360

    
2361
target_ulong helper_rdccr(void)
2362
{
2363
    return GET_CCR(env);
2364
}
2365

    
2366
void helper_wrccr(target_ulong new_ccr)
2367
{
2368
    PUT_CCR(env, new_ccr);
2369
}
2370

    
2371
// CWP handling is reversed in V9, but we still use the V8 register
2372
// order.
2373
target_ulong helper_rdcwp(void)
2374
{
2375
    return GET_CWP64(env);
2376
}
2377

    
2378
void helper_wrcwp(target_ulong new_cwp)
2379
{
2380
    PUT_CWP64(env, new_cwp);
2381
}
2382

    
2383
// This function uses non-native bit order
2384
#define GET_FIELD(X, FROM, TO)                                  \
2385
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2386

    
2387
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2388
#define GET_FIELD_SP(X, FROM, TO)               \
2389
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2390

    
2391
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2392
{
2393
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2394
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2395
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2396
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2397
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2398
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2399
        (((pixel_addr >> 55) & 1) << 4) |
2400
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2401
        GET_FIELD_SP(pixel_addr, 11, 12);
2402
}
2403

    
2404
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2405
{
2406
    uint64_t tmp;
2407

    
2408
    tmp = addr + offset;
2409
    env->gsr &= ~7ULL;
2410
    env->gsr |= tmp & 7ULL;
2411
    return tmp & ~7ULL;
2412
}
2413

    
2414
target_ulong helper_popc(target_ulong val)
2415
{
2416
    return ctpop64(val);
2417
}
2418

    
2419
static inline uint64_t *get_gregset(uint64_t pstate)
2420
{
2421
    switch (pstate) {
2422
    default:
2423
    case 0:
2424
        return env->bgregs;
2425
    case PS_AG:
2426
        return env->agregs;
2427
    case PS_MG:
2428
        return env->mgregs;
2429
    case PS_IG:
2430
        return env->igregs;
2431
    }
2432
}
2433

    
2434
static inline void change_pstate(uint64_t new_pstate)
2435
{
2436
    uint64_t pstate_regs, new_pstate_regs;
2437
    uint64_t *src, *dst;
2438

    
2439
    pstate_regs = env->pstate & 0xc01;
2440
    new_pstate_regs = new_pstate & 0xc01;
2441
    if (new_pstate_regs != pstate_regs) {
2442
        // Switch global register bank
2443
        src = get_gregset(new_pstate_regs);
2444
        dst = get_gregset(pstate_regs);
2445
        memcpy32(dst, env->gregs);
2446
        memcpy32(env->gregs, src);
2447
    }
2448
    env->pstate = new_pstate;
2449
}
2450

    
2451
void helper_wrpstate(target_ulong new_state)
2452
{
2453
    change_pstate(new_state & 0xf3f);
2454
}
2455

    
2456
void helper_done(void)
2457
{
2458
    env->tl--;
2459
    env->tsptr = &env->ts[env->tl];
2460
    env->pc = env->tsptr->tpc;
2461
    env->npc = env->tsptr->tnpc + 4;
2462
    PUT_CCR(env, env->tsptr->tstate >> 32);
2463
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2464
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2465
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2466
}
2467

    
2468
void helper_retry(void)
2469
{
2470
    env->tl--;
2471
    env->tsptr = &env->ts[env->tl];
2472
    env->pc = env->tsptr->tpc;
2473
    env->npc = env->tsptr->tnpc;
2474
    PUT_CCR(env, env->tsptr->tstate >> 32);
2475
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2476
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2477
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2478
}
2479
#endif
2480

    
2481
void set_cwp(int new_cwp)
2482
{
2483
    /* put the modified wrap registers at their proper location */
2484
    if (env->cwp == (NWINDOWS - 1))
2485
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2486
    env->cwp = new_cwp;
2487
    /* put the wrap registers at their temporary location */
2488
    if (new_cwp == (NWINDOWS - 1))
2489
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2490
    env->regwptr = env->regbase + (new_cwp * 16);
2491
    REGWPTR = env->regwptr;
2492
}
2493

    
2494
void cpu_set_cwp(CPUState *env1, int new_cwp)
2495
{
2496
    CPUState *saved_env;
2497
#ifdef reg_REGWPTR
2498
    target_ulong *saved_regwptr;
2499
#endif
2500

    
2501
    saved_env = env;
2502
#ifdef reg_REGWPTR
2503
    saved_regwptr = REGWPTR;
2504
#endif
2505
    env = env1;
2506
    set_cwp(new_cwp);
2507
    env = saved_env;
2508
#ifdef reg_REGWPTR
2509
    REGWPTR = saved_regwptr;
2510
#endif
2511
}
2512

    
2513
#ifdef TARGET_SPARC64
2514
#ifdef DEBUG_PCALL
2515
static const char * const excp_names[0x50] = {
2516
    [TT_TFAULT] = "Instruction Access Fault",
2517
    [TT_TMISS] = "Instruction Access MMU Miss",
2518
    [TT_CODE_ACCESS] = "Instruction Access Error",
2519
    [TT_ILL_INSN] = "Illegal Instruction",
2520
    [TT_PRIV_INSN] = "Privileged Instruction",
2521
    [TT_NFPU_INSN] = "FPU Disabled",
2522
    [TT_FP_EXCP] = "FPU Exception",
2523
    [TT_TOVF] = "Tag Overflow",
2524
    [TT_CLRWIN] = "Clean Windows",
2525
    [TT_DIV_ZERO] = "Division By Zero",
2526
    [TT_DFAULT] = "Data Access Fault",
2527
    [TT_DMISS] = "Data Access MMU Miss",
2528
    [TT_DATA_ACCESS] = "Data Access Error",
2529
    [TT_DPROT] = "Data Protection Error",
2530
    [TT_UNALIGNED] = "Unaligned Memory Access",
2531
    [TT_PRIV_ACT] = "Privileged Action",
2532
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2533
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2534
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2535
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2536
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2537
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2538
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2539
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2540
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2541
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2542
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2543
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2544
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2545
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2546
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2547
};
2548
#endif
2549

    
2550
void do_interrupt(int intno)
2551
{
2552
#ifdef DEBUG_PCALL
2553
    if (loglevel & CPU_LOG_INT) {
2554
        static int count;
2555
        const char *name;
2556

    
2557
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2558
            name = "Unknown";
2559
        else if (intno >= 0x100)
2560
            name = "Trap Instruction";
2561
        else if (intno >= 0xc0)
2562
            name = "Window Fill";
2563
        else if (intno >= 0x80)
2564
            name = "Window Spill";
2565
        else {
2566
            name = excp_names[intno];
2567
            if (!name)
2568
                name = "Unknown";
2569
        }
2570

    
2571
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2572
                " SP=%016" PRIx64 "\n",
2573
                count, name, intno,
2574
                env->pc,
2575
                env->npc, env->regwptr[6]);
2576
        cpu_dump_state(env, logfile, fprintf, 0);
2577
#if 0
2578
        {
2579
            int i;
2580
            uint8_t *ptr;
2581

2582
            fprintf(logfile, "       code=");
2583
            ptr = (uint8_t *)env->pc;
2584
            for(i = 0; i < 16; i++) {
2585
                fprintf(logfile, " %02x", ldub(ptr + i));
2586
            }
2587
            fprintf(logfile, "\n");
2588
        }
2589
#endif
2590
        count++;
2591
    }
2592
#endif
2593
#if !defined(CONFIG_USER_ONLY)
2594
    if (env->tl == MAXTL) {
2595
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
2596
        return;
2597
    }
2598
#endif
2599
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2600
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2601
        GET_CWP64(env);
2602
    env->tsptr->tpc = env->pc;
2603
    env->tsptr->tnpc = env->npc;
2604
    env->tsptr->tt = intno;
2605
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
2606

    
2607
    if (intno == TT_CLRWIN)
2608
        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
2609
    else if ((intno & 0x1c0) == TT_SPILL)
2610
        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
2611
    else if ((intno & 0x1c0) == TT_FILL)
2612
        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
2613
    env->tbr &= ~0x7fffULL;
2614
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2615
    if (env->tl < MAXTL - 1) {
2616
        env->tl++;
2617
    } else {
2618
        env->pstate |= PS_RED;
2619
        if (env->tl != MAXTL)
2620
            env->tl++;
2621
    }
2622
    env->tsptr = &env->ts[env->tl];
2623
    env->pc = env->tbr;
2624
    env->npc = env->pc + 4;
2625
    env->exception_index = 0;
2626
}
2627
#else
2628
#ifdef DEBUG_PCALL
2629
static const char * const excp_names[0x80] = {
2630
    [TT_TFAULT] = "Instruction Access Fault",
2631
    [TT_ILL_INSN] = "Illegal Instruction",
2632
    [TT_PRIV_INSN] = "Privileged Instruction",
2633
    [TT_NFPU_INSN] = "FPU Disabled",
2634
    [TT_WIN_OVF] = "Window Overflow",
2635
    [TT_WIN_UNF] = "Window Underflow",
2636
    [TT_UNALIGNED] = "Unaligned Memory Access",
2637
    [TT_FP_EXCP] = "FPU Exception",
2638
    [TT_DFAULT] = "Data Access Fault",
2639
    [TT_TOVF] = "Tag Overflow",
2640
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2641
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2642
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2643
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2644
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2645
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2646
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2647
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2648
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2649
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2650
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2651
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2652
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2653
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2654
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2655
    [TT_TOVF] = "Tag Overflow",
2656
    [TT_CODE_ACCESS] = "Instruction Access Error",
2657
    [TT_DATA_ACCESS] = "Data Access Error",
2658
    [TT_DIV_ZERO] = "Division By Zero",
2659
    [TT_NCP_INSN] = "Coprocessor Disabled",
2660
};
2661
#endif
2662

    
2663
void do_interrupt(int intno)
2664
{
2665
    int cwp;
2666

    
2667
#ifdef DEBUG_PCALL
2668
    if (loglevel & CPU_LOG_INT) {
2669
        static int count;
2670
        const char *name;
2671

    
2672
        if (intno < 0 || intno >= 0x100)
2673
            name = "Unknown";
2674
        else if (intno >= 0x80)
2675
            name = "Trap Instruction";
2676
        else {
2677
            name = excp_names[intno];
2678
            if (!name)
2679
                name = "Unknown";
2680
        }
2681

    
2682
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2683
                count, name, intno,
2684
                env->pc,
2685
                env->npc, env->regwptr[6]);
2686
        cpu_dump_state(env, logfile, fprintf, 0);
2687
#if 0
2688
        {
2689
            int i;
2690
            uint8_t *ptr;
2691

2692
            fprintf(logfile, "       code=");
2693
            ptr = (uint8_t *)env->pc;
2694
            for(i = 0; i < 16; i++) {
2695
                fprintf(logfile, " %02x", ldub(ptr + i));
2696
            }
2697
            fprintf(logfile, "\n");
2698
        }
2699
#endif
2700
        count++;
2701
    }
2702
#endif
2703
#if !defined(CONFIG_USER_ONLY)
2704
    if (env->psret == 0) {
2705
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
2706
        return;
2707
    }
2708
#endif
2709
    env->psret = 0;
2710
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2711
    set_cwp(cwp);
2712
    env->regwptr[9] = env->pc;
2713
    env->regwptr[10] = env->npc;
2714
    env->psrps = env->psrs;
2715
    env->psrs = 1;
2716
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2717
    env->pc = env->tbr;
2718
    env->npc = env->pc + 4;
2719
    env->exception_index = 0;
2720
}
2721
#endif
2722

    
2723
#if !defined(CONFIG_USER_ONLY)
2724

    
2725
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2726
                                void *retaddr);
2727

    
2728
#define MMUSUFFIX _mmu
2729
#define ALIGNED_ONLY
2730
#ifdef __s390__
2731
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2732
#else
2733
# define GETPC() (__builtin_return_address(0))
2734
#endif
2735

    
2736
#define SHIFT 0
2737
#include "softmmu_template.h"
2738

    
2739
#define SHIFT 1
2740
#include "softmmu_template.h"
2741

    
2742
#define SHIFT 2
2743
#include "softmmu_template.h"
2744

    
2745
#define SHIFT 3
2746
#include "softmmu_template.h"
2747

    
2748
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2749
                                void *retaddr)
2750
{
2751
#ifdef DEBUG_UNALIGNED
2752
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
2753
#endif
2754
    raise_exception(TT_UNALIGNED);
2755
}
2756

    
2757
/* try to fill the TLB and return an exception if error. If retaddr is
2758
   NULL, it means that the function was called in C code (i.e. not
2759
   from generated code or from helper.c) */
2760
/* XXX: fix it to restore all registers */
2761
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2762
{
2763
    TranslationBlock *tb;
2764
    int ret;
2765
    unsigned long pc;
2766
    CPUState *saved_env;
2767

    
2768
    /* XXX: hack to restore env in all cases, even if not called from
2769
       generated code */
2770
    saved_env = env;
2771
    env = cpu_single_env;
2772

    
2773
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2774
    if (ret) {
2775
        if (retaddr) {
2776
            /* now we have a real cpu fault */
2777
            pc = (unsigned long)retaddr;
2778
            tb = tb_find_pc(pc);
2779
            if (tb) {
2780
                /* the PC is inside the translated code. It means that we have
2781
                   a virtual CPU fault */
2782
                cpu_restore_state(tb, env, pc, (void *)T2);
2783
            }
2784
        }
2785
        cpu_loop_exit();
2786
    }
2787
    env = saved_env;
2788
}
2789

    
2790
#endif
2791

    
2792
#ifndef TARGET_SPARC64
2793
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2794
                          int is_asi)
2795
{
2796
    CPUState *saved_env;
2797

    
2798
    /* XXX: hack to restore env in all cases, even if not called from
2799
       generated code */
2800
    saved_env = env;
2801
    env = cpu_single_env;
2802
#ifdef DEBUG_UNASSIGNED
2803
    if (is_asi)
2804
        printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2805
               TARGET_FMT_lx "\n",
2806
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2807
               env->pc);
2808
    else
2809
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2810
               TARGET_FMT_lx "\n",
2811
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2812
#endif
2813
    if (env->mmuregs[3]) /* Fault status register */
2814
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2815
    if (is_asi)
2816
        env->mmuregs[3] |= 1 << 16;
2817
    if (env->psrs)
2818
        env->mmuregs[3] |= 1 << 5;
2819
    if (is_exec)
2820
        env->mmuregs[3] |= 1 << 6;
2821
    if (is_write)
2822
        env->mmuregs[3] |= 1 << 7;
2823
    env->mmuregs[3] |= (5 << 2) | 2;
2824
    env->mmuregs[4] = addr; /* Fault address register */
2825
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2826
        if (is_exec)
2827
            raise_exception(TT_CODE_ACCESS);
2828
        else
2829
            raise_exception(TT_DATA_ACCESS);
2830
    }
2831
    env = saved_env;
2832
}
2833
#else
2834
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2835
                          int is_asi)
2836
{
2837
#ifdef DEBUG_UNASSIGNED
2838
    CPUState *saved_env;
2839

    
2840
    /* XXX: hack to restore env in all cases, even if not called from
2841
       generated code */
2842
    saved_env = env;
2843
    env = cpu_single_env;
2844
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2845
           addr, env->pc);
2846
    env = saved_env;
2847
#endif
2848
    if (is_exec)
2849
        raise_exception(TT_CODE_ACCESS);
2850
    else
2851
        raise_exception(TT_DATA_ACCESS);
2852
}
2853
#endif
2854