Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 7c60cc4b

History | View | Annotate | Download (79.4 kB)

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

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

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

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

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

    
36
void raise_exception(int tt)
37
{
38
    env->exception_index = tt;
39
    cpu_loop_exit();
40
}
41

    
42
void helper_trap(target_ulong nb_trap)
43
{
44
    env->exception_index = TT_TRAP + (nb_trap & 0x7f);
45
    cpu_loop_exit();
46
}
47

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

    
56
void helper_check_align(target_ulong addr, uint32_t align)
57
{
58
    if (addr & align)
59
        raise_exception(TT_UNALIGNED);
60
}
61

    
62
#define F_HELPER(name, p) void helper_f##name##p(void)
63

    
64
#define F_BINOP(name)                                           \
65
    F_HELPER(name, s)                                           \
66
    {                                                           \
67
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
68
    }                                                           \
69
    F_HELPER(name, d)                                           \
70
    {                                                           \
71
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
72
    }                                                           \
73
    F_HELPER(name, q)                                           \
74
    {                                                           \
75
        QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
76
    }
77

    
78
F_BINOP(add);
79
F_BINOP(sub);
80
F_BINOP(mul);
81
F_BINOP(div);
82
#undef F_BINOP
83

    
84
void helper_fsmuld(void)
85
{
86
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
87
                      float32_to_float64(FT1, &env->fp_status),
88
                      &env->fp_status);
89
}
90

    
91
void helper_fdmulq(void)
92
{
93
    QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
94
                       float64_to_float128(DT1, &env->fp_status),
95
                       &env->fp_status);
96
}
97

    
98
F_HELPER(neg, s)
99
{
100
    FT0 = float32_chs(FT1);
101
}
102

    
103
#ifdef TARGET_SPARC64
104
F_HELPER(neg, d)
105
{
106
    DT0 = float64_chs(DT1);
107
}
108

    
109
F_HELPER(neg, q)
110
{
111
    QT0 = float128_chs(QT1);
112
}
113
#endif
114

    
115
/* Integer to float conversion.  */
116
F_HELPER(ito, s)
117
{
118
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
119
}
120

    
121
F_HELPER(ito, d)
122
{
123
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
124
}
125

    
126
F_HELPER(ito, q)
127
{
128
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
129
}
130

    
131
#ifdef TARGET_SPARC64
132
F_HELPER(xto, s)
133
{
134
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
135
}
136

    
137
F_HELPER(xto, d)
138
{
139
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
140
}
141

    
142
F_HELPER(xto, q)
143
{
144
    QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
145
}
146
#endif
147
#undef F_HELPER
148

    
149
/* floating point conversion */
150
void helper_fdtos(void)
151
{
152
    FT0 = float64_to_float32(DT1, &env->fp_status);
153
}
154

    
155
void helper_fstod(void)
156
{
157
    DT0 = float32_to_float64(FT1, &env->fp_status);
158
}
159

    
160
void helper_fqtos(void)
161
{
162
    FT0 = float128_to_float32(QT1, &env->fp_status);
163
}
164

    
165
void helper_fstoq(void)
166
{
167
    QT0 = float32_to_float128(FT1, &env->fp_status);
168
}
169

    
170
void helper_fqtod(void)
171
{
172
    DT0 = float128_to_float64(QT1, &env->fp_status);
173
}
174

    
175
void helper_fdtoq(void)
176
{
177
    QT0 = float64_to_float128(DT1, &env->fp_status);
178
}
179

    
180
/* Float to integer conversion.  */
181
void helper_fstoi(void)
182
{
183
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
184
}
185

    
186
void helper_fdtoi(void)
187
{
188
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
189
}
190

    
191
void helper_fqtoi(void)
192
{
193
    *((int32_t *)&FT0) = float128_to_int32_round_to_zero(QT1, &env->fp_status);
194
}
195

    
196
#ifdef TARGET_SPARC64
197
void helper_fstox(void)
198
{
199
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
200
}
201

    
202
void helper_fdtox(void)
203
{
204
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
205
}
206

    
207
void helper_fqtox(void)
208
{
209
    *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
210
}
211

    
212
void helper_faligndata(void)
213
{
214
    uint64_t tmp;
215

    
216
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
217
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
218
    *((uint64_t *)&DT0) = tmp;
219
}
220

    
221
void helper_movl_FT0_0(void)
222
{
223
    *((uint32_t *)&FT0) = 0;
224
}
225

    
226
void helper_movl_DT0_0(void)
227
{
228
    *((uint64_t *)&DT0) = 0;
229
}
230

    
231
void helper_movl_FT0_1(void)
232
{
233
    *((uint32_t *)&FT0) = 0xffffffff;
234
}
235

    
236
void helper_movl_DT0_1(void)
237
{
238
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
239
}
240

    
241
void helper_fnot(void)
242
{
243
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
244
}
245

    
246
void helper_fnots(void)
247
{
248
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
249
}
250

    
251
void helper_fnor(void)
252
{
253
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
254
}
255

    
256
void helper_fnors(void)
257
{
258
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
259
}
260

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

    
266
void helper_fors(void)
267
{
268
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
269
}
270

    
271
void helper_fxor(void)
272
{
273
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
274
}
275

    
276
void helper_fxors(void)
277
{
278
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
279
}
280

    
281
void helper_fand(void)
282
{
283
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
284
}
285

    
286
void helper_fands(void)
287
{
288
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
289
}
290

    
291
void helper_fornot(void)
292
{
293
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
294
}
295

    
296
void helper_fornots(void)
297
{
298
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
299
}
300

    
301
void helper_fandnot(void)
302
{
303
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 & ~*(uint64_t *)&DT1;
304
}
305

    
306
void helper_fandnots(void)
307
{
308
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 & ~*(uint32_t *)&FT1;
309
}
310

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

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

    
321
void helper_fxnor(void)
322
{
323
    *(uint64_t *)&DT0 ^= ~*(uint64_t *)&DT1;
324
}
325

    
326
void helper_fxnors(void)
327
{
328
    *(uint32_t *)&FT0 ^= ~*(uint32_t *)&FT1;
329
}
330

    
331
#ifdef WORDS_BIGENDIAN
332
#define VIS_B64(n) b[7 - (n)]
333
#define VIS_W64(n) w[3 - (n)]
334
#define VIS_SW64(n) sw[3 - (n)]
335
#define VIS_L64(n) l[1 - (n)]
336
#define VIS_B32(n) b[3 - (n)]
337
#define VIS_W32(n) w[1 - (n)]
338
#else
339
#define VIS_B64(n) b[n]
340
#define VIS_W64(n) w[n]
341
#define VIS_SW64(n) sw[n]
342
#define VIS_L64(n) l[n]
343
#define VIS_B32(n) b[n]
344
#define VIS_W32(n) w[n]
345
#endif
346

    
347
typedef union {
348
    uint8_t b[8];
349
    uint16_t w[4];
350
    int16_t sw[4];
351
    uint32_t l[2];
352
    float64 d;
353
} vis64;
354

    
355
typedef union {
356
    uint8_t b[4];
357
    uint16_t w[2];
358
    uint32_t l;
359
    float32 f;
360
} vis32;
361

    
362
void helper_fpmerge(void)
363
{
364
    vis64 s, d;
365

    
366
    s.d = DT0;
367
    d.d = DT1;
368

    
369
    // Reverse calculation order to handle overlap
370
    d.VIS_B64(7) = s.VIS_B64(3);
371
    d.VIS_B64(6) = d.VIS_B64(3);
372
    d.VIS_B64(5) = s.VIS_B64(2);
373
    d.VIS_B64(4) = d.VIS_B64(2);
374
    d.VIS_B64(3) = s.VIS_B64(1);
375
    d.VIS_B64(2) = d.VIS_B64(1);
376
    d.VIS_B64(1) = s.VIS_B64(0);
377
    //d.VIS_B64(0) = d.VIS_B64(0);
378

    
379
    DT0 = d.d;
380
}
381

    
382
void helper_fmul8x16(void)
383
{
384
    vis64 s, d;
385
    uint32_t tmp;
386

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

    
390
#define PMUL(r)                                                 \
391
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
392
    if ((tmp & 0xff) > 0x7f)                                    \
393
        tmp += 0x100;                                           \
394
    d.VIS_W64(r) = tmp >> 8;
395

    
396
    PMUL(0);
397
    PMUL(1);
398
    PMUL(2);
399
    PMUL(3);
400
#undef PMUL
401

    
402
    DT0 = d.d;
403
}
404

    
405
void helper_fmul8x16al(void)
406
{
407
    vis64 s, d;
408
    uint32_t tmp;
409

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

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

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

    
425
    DT0 = d.d;
426
}
427

    
428
void helper_fmul8x16au(void)
429
{
430
    vis64 s, d;
431
    uint32_t tmp;
432

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

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

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

    
448
    DT0 = d.d;
449
}
450

    
451
void helper_fmul8sux16(void)
452
{
453
    vis64 s, d;
454
    uint32_t tmp;
455

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

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

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

    
471
    DT0 = d.d;
472
}
473

    
474
void helper_fmul8ulx16(void)
475
{
476
    vis64 s, d;
477
    uint32_t tmp;
478

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

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

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

    
494
    DT0 = d.d;
495
}
496

    
497
void helper_fmuld8sux16(void)
498
{
499
    vis64 s, d;
500
    uint32_t tmp;
501

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

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

    
511
    // Reverse calculation order to handle overlap
512
    PMUL(1);
513
    PMUL(0);
514
#undef PMUL
515

    
516
    DT0 = d.d;
517
}
518

    
519
void helper_fmuld8ulx16(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) * ((uint32_t)s.VIS_B64(r * 2));        \
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_fexpand(void)
542
{
543
    vis32 s;
544
    vis64 d;
545

    
546
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
547
    d.d = DT1;
548
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
549
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
550
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
551
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
552

    
553
    DT0 = d.d;
554
}
555

    
556
#define VIS_HELPER(name, F)                             \
557
    void name##16(void)                                 \
558
    {                                                   \
559
        vis64 s, d;                                     \
560
                                                        \
561
        s.d = DT0;                                      \
562
        d.d = DT1;                                      \
563
                                                        \
564
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
565
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
566
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
567
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
568
                                                        \
569
        DT0 = d.d;                                      \
570
    }                                                   \
571
                                                        \
572
    void name##16s(void)                                \
573
    {                                                   \
574
        vis32 s, d;                                     \
575
                                                        \
576
        s.f = FT0;                                      \
577
        d.f = FT1;                                      \
578
                                                        \
579
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
580
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
581
                                                        \
582
        FT0 = d.f;                                      \
583
    }                                                   \
584
                                                        \
585
    void name##32(void)                                 \
586
    {                                                   \
587
        vis64 s, d;                                     \
588
                                                        \
589
        s.d = DT0;                                      \
590
        d.d = DT1;                                      \
591
                                                        \
592
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
593
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
594
                                                        \
595
        DT0 = d.d;                                      \
596
    }                                                   \
597
                                                        \
598
    void name##32s(void)                                \
599
    {                                                   \
600
        vis32 s, d;                                     \
601
                                                        \
602
        s.f = FT0;                                      \
603
        d.f = FT1;                                      \
604
                                                        \
605
        d.l = F(d.l, s.l);                              \
606
                                                        \
607
        FT0 = d.f;                                      \
608
    }
609

    
610
#define FADD(a, b) ((a) + (b))
611
#define FSUB(a, b) ((a) - (b))
612
VIS_HELPER(helper_fpadd, FADD)
613
VIS_HELPER(helper_fpsub, FSUB)
614

    
615
#define VIS_CMPHELPER(name, F)                                        \
616
    void name##16(void)                                           \
617
    {                                                             \
618
        vis64 s, d;                                               \
619
                                                                  \
620
        s.d = DT0;                                                \
621
        d.d = DT1;                                                \
622
                                                                  \
623
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
624
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
625
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
626
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
627
                                                                  \
628
        DT0 = d.d;                                                \
629
    }                                                             \
630
                                                                  \
631
    void name##32(void)                                           \
632
    {                                                             \
633
        vis64 s, d;                                               \
634
                                                                  \
635
        s.d = DT0;                                                \
636
        d.d = DT1;                                                \
637
                                                                  \
638
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
639
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
640
                                                                  \
641
        DT0 = d.d;                                                \
642
    }
643

    
644
#define FCMPGT(a, b) ((a) > (b))
645
#define FCMPEQ(a, b) ((a) == (b))
646
#define FCMPLE(a, b) ((a) <= (b))
647
#define FCMPNE(a, b) ((a) != (b))
648

    
649
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
650
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
651
VIS_CMPHELPER(helper_fcmple, FCMPLE)
652
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
653
#endif
654

    
655
void helper_check_ieee_exceptions(void)
656
{
657
    target_ulong status;
658

    
659
    status = get_float_exception_flags(&env->fp_status);
660
    if (status) {
661
        /* Copy IEEE 754 flags into FSR */
662
        if (status & float_flag_invalid)
663
            env->fsr |= FSR_NVC;
664
        if (status & float_flag_overflow)
665
            env->fsr |= FSR_OFC;
666
        if (status & float_flag_underflow)
667
            env->fsr |= FSR_UFC;
668
        if (status & float_flag_divbyzero)
669
            env->fsr |= FSR_DZC;
670
        if (status & float_flag_inexact)
671
            env->fsr |= FSR_NXC;
672

    
673
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
674
            /* Unmasked exception, generate a trap */
675
            env->fsr |= FSR_FTT_IEEE_EXCP;
676
            raise_exception(TT_FP_EXCP);
677
        } else {
678
            /* Accumulate exceptions */
679
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
680
        }
681
    }
682
}
683

    
684
void helper_clear_float_exceptions(void)
685
{
686
    set_float_exception_flags(0, &env->fp_status);
687
}
688

    
689
void helper_fabss(void)
690
{
691
    FT0 = float32_abs(FT1);
692
}
693

    
694
#ifdef TARGET_SPARC64
695
void helper_fabsd(void)
696
{
697
    DT0 = float64_abs(DT1);
698
}
699

    
700
void helper_fabsq(void)
701
{
702
    QT0 = float128_abs(QT1);
703
}
704
#endif
705

    
706
void helper_fsqrts(void)
707
{
708
    FT0 = float32_sqrt(FT1, &env->fp_status);
709
}
710

    
711
void helper_fsqrtd(void)
712
{
713
    DT0 = float64_sqrt(DT1, &env->fp_status);
714
}
715

    
716
void helper_fsqrtq(void)
717
{
718
    QT0 = float128_sqrt(QT1, &env->fp_status);
719
}
720

    
721
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
722
    void glue(helper_, name) (void)                                     \
723
    {                                                                   \
724
        target_ulong new_fsr;                                           \
725
                                                                        \
726
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
727
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
728
        case float_relation_unordered:                                  \
729
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
730
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
731
                env->fsr |= new_fsr;                                    \
732
                env->fsr |= FSR_NVC;                                    \
733
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
734
                raise_exception(TT_FP_EXCP);                            \
735
            } else {                                                    \
736
                env->fsr |= FSR_NVA;                                    \
737
            }                                                           \
738
            break;                                                      \
739
        case float_relation_less:                                       \
740
            new_fsr = FSR_FCC0 << FS;                                   \
741
            break;                                                      \
742
        case float_relation_greater:                                    \
743
            new_fsr = FSR_FCC1 << FS;                                   \
744
            break;                                                      \
745
        default:                                                        \
746
            new_fsr = 0;                                                \
747
            break;                                                      \
748
        }                                                               \
749
        env->fsr |= new_fsr;                                            \
750
    }
751

    
752
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
753
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
754

    
755
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
756
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
757

    
758
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
759
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
760

    
761
#ifdef TARGET_SPARC64
762
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
763
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
764
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
765

    
766
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
767
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
768
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
769

    
770
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
771
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
772
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
773

    
774
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
775
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
776
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
777

    
778
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
779
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
780
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
781

    
782
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
783
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
784
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
785
#endif
786

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

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

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

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

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

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

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

    
1118
            mmulev = (addr >> 8) & 15;
1119
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1120
            switch (mmulev) {
1121
            case 0: // flush page
1122
                tlb_flush_page(env, addr & 0xfffff000);
1123
                break;
1124
            case 1: // flush segment (256k)
1125
            case 2: // flush region (16M)
1126
            case 3: // flush context (4G)
1127
            case 4: // flush entire
1128
                tlb_flush(env, 1);
1129
                break;
1130
            default:
1131
                break;
1132
            }
1133
#ifdef DEBUG_MMU
1134
            dump_mmu(env);
1135
#endif
1136
        }
1137
        break;
1138
    case 4: /* write MMU regs */
1139
        {
1140
            int reg = (addr >> 8) & 0x1f;
1141
            uint32_t oldreg;
1142

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

    
1245
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1246
                temp = ldl_kernel(src);
1247
                stl_kernel(dst, temp);
1248
            }
1249
        }
1250
        break;
1251
    case 0x1f: /* Block fill, stda access */
1252
        {
1253
            // addr = dst
1254
            // fill 32 bytes with val
1255
            unsigned int i;
1256
            uint32_t dst = addr & 7;
1257

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

    
1324
#endif /* CONFIG_USER_ONLY */
1325
#else /* TARGET_SPARC64 */
1326

    
1327
#ifdef CONFIG_USER_ONLY
1328
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1329
{
1330
    uint64_t ret = 0;
1331
#if defined(DEBUG_ASI)
1332
    target_ulong last_addr = addr;
1333
#endif
1334

    
1335
    if (asi < 0x80)
1336
        raise_exception(TT_PRIV_ACT);
1337

    
1338
    switch (asi) {
1339
    case 0x80: // Primary
1340
    case 0x82: // Primary no-fault
1341
    case 0x88: // Primary LE
1342
    case 0x8a: // Primary no-fault LE
1343
        {
1344
            switch(size) {
1345
            case 1:
1346
                ret = ldub_raw(addr);
1347
                break;
1348
            case 2:
1349
                ret = lduw_raw(addr & ~1);
1350
                break;
1351
            case 4:
1352
                ret = ldl_raw(addr & ~3);
1353
                break;
1354
            default:
1355
            case 8:
1356
                ret = ldq_raw(addr & ~7);
1357
                break;
1358
            }
1359
        }
1360
        break;
1361
    case 0x81: // Secondary
1362
    case 0x83: // Secondary no-fault
1363
    case 0x89: // Secondary LE
1364
    case 0x8b: // Secondary no-fault LE
1365
        // XXX
1366
        break;
1367
    default:
1368
        break;
1369
    }
1370

    
1371
    /* Convert from little endian */
1372
    switch (asi) {
1373
    case 0x88: // Primary LE
1374
    case 0x89: // Secondary LE
1375
    case 0x8a: // Primary no-fault LE
1376
    case 0x8b: // Secondary no-fault LE
1377
        switch(size) {
1378
        case 2:
1379
            ret = bswap16(ret);
1380
            break;
1381
        case 4:
1382
            ret = bswap32(ret);
1383
            break;
1384
        case 8:
1385
            ret = bswap64(ret);
1386
            break;
1387
        default:
1388
            break;
1389
        }
1390
    default:
1391
        break;
1392
    }
1393

    
1394
    /* Convert to signed number */
1395
    if (sign) {
1396
        switch(size) {
1397
        case 1:
1398
            ret = (int8_t) ret;
1399
            break;
1400
        case 2:
1401
            ret = (int16_t) ret;
1402
            break;
1403
        case 4:
1404
            ret = (int32_t) ret;
1405
            break;
1406
        default:
1407
            break;
1408
        }
1409
    }
1410
#ifdef DEBUG_ASI
1411
    dump_asi("read ", last_addr, asi, size, ret);
1412
#endif
1413
    return ret;
1414
}
1415

    
1416
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1417
{
1418
#ifdef DEBUG_ASI
1419
    dump_asi("write", addr, asi, size, val);
1420
#endif
1421
    if (asi < 0x80)
1422
        raise_exception(TT_PRIV_ACT);
1423

    
1424
    /* Convert to little endian */
1425
    switch (asi) {
1426
    case 0x88: // Primary LE
1427
    case 0x89: // Secondary LE
1428
        switch(size) {
1429
        case 2:
1430
            addr = bswap16(addr);
1431
            break;
1432
        case 4:
1433
            addr = bswap32(addr);
1434
            break;
1435
        case 8:
1436
            addr = bswap64(addr);
1437
            break;
1438
        default:
1439
            break;
1440
        }
1441
    default:
1442
        break;
1443
    }
1444

    
1445
    switch(asi) {
1446
    case 0x80: // Primary
1447
    case 0x88: // Primary LE
1448
        {
1449
            switch(size) {
1450
            case 1:
1451
                stb_raw(addr, val);
1452
                break;
1453
            case 2:
1454
                stw_raw(addr & ~1, val);
1455
                break;
1456
            case 4:
1457
                stl_raw(addr & ~3, val);
1458
                break;
1459
            case 8:
1460
            default:
1461
                stq_raw(addr & ~7, val);
1462
                break;
1463
            }
1464
        }
1465
        break;
1466
    case 0x81: // Secondary
1467
    case 0x89: // Secondary LE
1468
        // XXX
1469
        return;
1470

    
1471
    case 0x82: // Primary no-fault, RO
1472
    case 0x83: // Secondary no-fault, RO
1473
    case 0x8a: // Primary no-fault LE, RO
1474
    case 0x8b: // Secondary no-fault LE, RO
1475
    default:
1476
        do_unassigned_access(addr, 1, 0, 1);
1477
        return;
1478
    }
1479
}
1480

    
1481
#else /* CONFIG_USER_ONLY */
1482

    
1483
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1484
{
1485
    uint64_t ret = 0;
1486
#if defined(DEBUG_ASI)
1487
    target_ulong last_addr = addr;
1488
#endif
1489

    
1490
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1491
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1492
        raise_exception(TT_PRIV_ACT);
1493

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

    
1595
            ret = env->immuregs[reg];
1596
            break;
1597
        }
1598
    case 0x51: // I-MMU 8k TSB pointer
1599
    case 0x52: // I-MMU 64k TSB pointer
1600
    case 0x55: // I-MMU data access
1601
        // XXX
1602
        break;
1603
    case 0x56: // I-MMU tag read
1604
        {
1605
            unsigned int i;
1606

    
1607
            for (i = 0; i < 64; i++) {
1608
                // Valid, ctx match, vaddr match
1609
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1610
                    env->itlb_tag[i] == addr) {
1611
                    ret = env->itlb_tag[i];
1612
                    break;
1613
                }
1614
            }
1615
            break;
1616
        }
1617
    case 0x58: // D-MMU regs
1618
        {
1619
            int reg = (addr >> 3) & 0xf;
1620

    
1621
            ret = env->dmmuregs[reg];
1622
            break;
1623
        }
1624
    case 0x5e: // D-MMU tag read
1625
        {
1626
            unsigned int i;
1627

    
1628
            for (i = 0; i < 64; i++) {
1629
                // Valid, ctx match, vaddr match
1630
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1631
                    env->dtlb_tag[i] == addr) {
1632
                    ret = env->dtlb_tag[i];
1633
                    break;
1634
                }
1635
            }
1636
            break;
1637
        }
1638
    case 0x59: // D-MMU 8k TSB pointer
1639
    case 0x5a: // D-MMU 64k TSB pointer
1640
    case 0x5b: // D-MMU data pointer
1641
    case 0x5d: // D-MMU data access
1642
    case 0x48: // Interrupt dispatch, RO
1643
    case 0x49: // Interrupt data receive
1644
    case 0x7f: // Incoming interrupt vector, RO
1645
        // XXX
1646
        break;
1647
    case 0x54: // I-MMU data in, WO
1648
    case 0x57: // I-MMU demap, WO
1649
    case 0x5c: // D-MMU data in, WO
1650
    case 0x5f: // D-MMU demap, WO
1651
    case 0x77: // Interrupt vector, WO
1652
    default:
1653
        do_unassigned_access(addr, 0, 0, 1);
1654
        ret = 0;
1655
        break;
1656
    }
1657

    
1658
    /* Convert from little endian */
1659
    switch (asi) {
1660
    case 0x0c: // Nucleus Little Endian (LE)
1661
    case 0x18: // As if user primary LE
1662
    case 0x19: // As if user secondary LE
1663
    case 0x1c: // Bypass LE
1664
    case 0x1d: // Bypass, non-cacheable LE
1665
    case 0x88: // Primary LE
1666
    case 0x89: // Secondary LE
1667
    case 0x8a: // Primary no-fault LE
1668
    case 0x8b: // Secondary no-fault LE
1669
        switch(size) {
1670
        case 2:
1671
            ret = bswap16(ret);
1672
            break;
1673
        case 4:
1674
            ret = bswap32(ret);
1675
            break;
1676
        case 8:
1677
            ret = bswap64(ret);
1678
            break;
1679
        default:
1680
            break;
1681
        }
1682
    default:
1683
        break;
1684
    }
1685

    
1686
    /* Convert to signed number */
1687
    if (sign) {
1688
        switch(size) {
1689
        case 1:
1690
            ret = (int8_t) ret;
1691
            break;
1692
        case 2:
1693
            ret = (int16_t) ret;
1694
            break;
1695
        case 4:
1696
            ret = (int32_t) ret;
1697
            break;
1698
        default:
1699
            break;
1700
        }
1701
    }
1702
#ifdef DEBUG_ASI
1703
    dump_asi("read ", last_addr, asi, size, ret);
1704
#endif
1705
    return ret;
1706
}
1707

    
1708
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1709
{
1710
#ifdef DEBUG_ASI
1711
    dump_asi("write", addr, asi, size, val);
1712
#endif
1713
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1714
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1715
        raise_exception(TT_PRIV_ACT);
1716

    
1717
    /* Convert to little endian */
1718
    switch (asi) {
1719
    case 0x0c: // Nucleus Little Endian (LE)
1720
    case 0x18: // As if user primary LE
1721
    case 0x19: // As if user secondary LE
1722
    case 0x1c: // Bypass LE
1723
    case 0x1d: // Bypass, non-cacheable LE
1724
    case 0x88: // Primary LE
1725
    case 0x89: // Secondary LE
1726
        switch(size) {
1727
        case 2:
1728
            addr = bswap16(addr);
1729
            break;
1730
        case 4:
1731
            addr = bswap32(addr);
1732
            break;
1733
        case 8:
1734
            addr = bswap64(addr);
1735
            break;
1736
        default:
1737
            break;
1738
        }
1739
    default:
1740
        break;
1741
    }
1742

    
1743
    switch(asi) {
1744
    case 0x10: // As if user primary
1745
    case 0x18: // As if user primary LE
1746
    case 0x80: // Primary
1747
    case 0x88: // Primary LE
1748
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1749
            if (env->hpstate & HS_PRIV) {
1750
                switch(size) {
1751
                case 1:
1752
                    stb_hypv(addr, val);
1753
                    break;
1754
                case 2:
1755
                    stw_hypv(addr & ~1, val);
1756
                    break;
1757
                case 4:
1758
                    stl_hypv(addr & ~3, val);
1759
                    break;
1760
                case 8:
1761
                default:
1762
                    stq_hypv(addr & ~7, val);
1763
                    break;
1764
                }
1765
            } else {
1766
                switch(size) {
1767
                case 1:
1768
                    stb_kernel(addr, val);
1769
                    break;
1770
                case 2:
1771
                    stw_kernel(addr & ~1, val);
1772
                    break;
1773
                case 4:
1774
                    stl_kernel(addr & ~3, val);
1775
                    break;
1776
                case 8:
1777
                default:
1778
                    stq_kernel(addr & ~7, val);
1779
                    break;
1780
                }
1781
            }
1782
        } else {
1783
            switch(size) {
1784
            case 1:
1785
                stb_user(addr, val);
1786
                break;
1787
            case 2:
1788
                stw_user(addr & ~1, val);
1789
                break;
1790
            case 4:
1791
                stl_user(addr & ~3, val);
1792
                break;
1793
            case 8:
1794
            default:
1795
                stq_user(addr & ~7, val);
1796
                break;
1797
            }
1798
        }
1799
        break;
1800
    case 0x14: // Bypass
1801
    case 0x15: // Bypass, non-cacheable
1802
    case 0x1c: // Bypass LE
1803
    case 0x1d: // Bypass, non-cacheable LE
1804
        {
1805
            switch(size) {
1806
            case 1:
1807
                stb_phys(addr, val);
1808
                break;
1809
            case 2:
1810
                stw_phys(addr & ~1, val);
1811
                break;
1812
            case 4:
1813
                stl_phys(addr & ~3, val);
1814
                break;
1815
            case 8:
1816
            default:
1817
                stq_phys(addr & ~7, val);
1818
                break;
1819
            }
1820
        }
1821
        return;
1822
    case 0x04: // Nucleus
1823
    case 0x0c: // Nucleus Little Endian (LE)
1824
    case 0x11: // As if user secondary
1825
    case 0x19: // As if user secondary LE
1826
    case 0x24: // Nucleus quad LDD 128 bit atomic
1827
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1828
    case 0x4a: // UPA config
1829
    case 0x81: // Secondary
1830
    case 0x89: // Secondary LE
1831
        // XXX
1832
        return;
1833
    case 0x45: // LSU
1834
        {
1835
            uint64_t oldreg;
1836

    
1837
            oldreg = env->lsu;
1838
            env->lsu = val & (DMMU_E | IMMU_E);
1839
            // Mappings generated during D/I MMU disabled mode are
1840
            // invalid in normal mode
1841
            if (oldreg != env->lsu) {
1842
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1843
#ifdef DEBUG_MMU
1844
                dump_mmu(env);
1845
#endif
1846
                tlb_flush(env, 1);
1847
            }
1848
            return;
1849
        }
1850
    case 0x50: // I-MMU regs
1851
        {
1852
            int reg = (addr >> 3) & 0xf;
1853
            uint64_t oldreg;
1854

    
1855
            oldreg = env->immuregs[reg];
1856
            switch(reg) {
1857
            case 0: // RO
1858
            case 4:
1859
                return;
1860
            case 1: // Not in I-MMU
1861
            case 2:
1862
            case 7:
1863
            case 8:
1864
                return;
1865
            case 3: // SFSR
1866
                if ((val & 1) == 0)
1867
                    val = 0; // Clear SFSR
1868
                break;
1869
            case 5: // TSB access
1870
            case 6: // Tag access
1871
            default:
1872
                break;
1873
            }
1874
            env->immuregs[reg] = val;
1875
            if (oldreg != env->immuregs[reg]) {
1876
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1877
            }
1878
#ifdef DEBUG_MMU
1879
            dump_mmu(env);
1880
#endif
1881
            return;
1882
        }
1883
    case 0x54: // I-MMU data in
1884
        {
1885
            unsigned int i;
1886

    
1887
            // Try finding an invalid entry
1888
            for (i = 0; i < 64; i++) {
1889
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1890
                    env->itlb_tag[i] = env->immuregs[6];
1891
                    env->itlb_tte[i] = val;
1892
                    return;
1893
                }
1894
            }
1895
            // Try finding an unlocked entry
1896
            for (i = 0; i < 64; i++) {
1897
                if ((env->itlb_tte[i] & 0x40) == 0) {
1898
                    env->itlb_tag[i] = env->immuregs[6];
1899
                    env->itlb_tte[i] = val;
1900
                    return;
1901
                }
1902
            }
1903
            // error state?
1904
            return;
1905
        }
1906
    case 0x55: // I-MMU data access
1907
        {
1908
            unsigned int i = (addr >> 3) & 0x3f;
1909

    
1910
            env->itlb_tag[i] = env->immuregs[6];
1911
            env->itlb_tte[i] = val;
1912
            return;
1913
        }
1914
    case 0x57: // I-MMU demap
1915
        // XXX
1916
        return;
1917
    case 0x58: // D-MMU regs
1918
        {
1919
            int reg = (addr >> 3) & 0xf;
1920
            uint64_t oldreg;
1921

    
1922
            oldreg = env->dmmuregs[reg];
1923
            switch(reg) {
1924
            case 0: // RO
1925
            case 4:
1926
                return;
1927
            case 3: // SFSR
1928
                if ((val & 1) == 0) {
1929
                    val = 0; // Clear SFSR, Fault address
1930
                    env->dmmuregs[4] = 0;
1931
                }
1932
                env->dmmuregs[reg] = val;
1933
                break;
1934
            case 1: // Primary context
1935
            case 2: // Secondary context
1936
            case 5: // TSB access
1937
            case 6: // Tag access
1938
            case 7: // Virtual Watchpoint
1939
            case 8: // Physical Watchpoint
1940
            default:
1941
                break;
1942
            }
1943
            env->dmmuregs[reg] = val;
1944
            if (oldreg != env->dmmuregs[reg]) {
1945
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1946
            }
1947
#ifdef DEBUG_MMU
1948
            dump_mmu(env);
1949
#endif
1950
            return;
1951
        }
1952
    case 0x5c: // D-MMU data in
1953
        {
1954
            unsigned int i;
1955

    
1956
            // Try finding an invalid entry
1957
            for (i = 0; i < 64; i++) {
1958
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1959
                    env->dtlb_tag[i] = env->dmmuregs[6];
1960
                    env->dtlb_tte[i] = val;
1961
                    return;
1962
                }
1963
            }
1964
            // Try finding an unlocked entry
1965
            for (i = 0; i < 64; i++) {
1966
                if ((env->dtlb_tte[i] & 0x40) == 0) {
1967
                    env->dtlb_tag[i] = env->dmmuregs[6];
1968
                    env->dtlb_tte[i] = val;
1969
                    return;
1970
                }
1971
            }
1972
            // error state?
1973
            return;
1974
        }
1975
    case 0x5d: // D-MMU data access
1976
        {
1977
            unsigned int i = (addr >> 3) & 0x3f;
1978

    
1979
            env->dtlb_tag[i] = env->dmmuregs[6];
1980
            env->dtlb_tte[i] = val;
1981
            return;
1982
        }
1983
    case 0x5f: // D-MMU demap
1984
    case 0x49: // Interrupt data receive
1985
        // XXX
1986
        return;
1987
    case 0x51: // I-MMU 8k TSB pointer, RO
1988
    case 0x52: // I-MMU 64k TSB pointer, RO
1989
    case 0x56: // I-MMU tag read, RO
1990
    case 0x59: // D-MMU 8k TSB pointer, RO
1991
    case 0x5a: // D-MMU 64k TSB pointer, RO
1992
    case 0x5b: // D-MMU data pointer, RO
1993
    case 0x5e: // D-MMU tag read, RO
1994
    case 0x48: // Interrupt dispatch, RO
1995
    case 0x7f: // Incoming interrupt vector, RO
1996
    case 0x82: // Primary no-fault, RO
1997
    case 0x83: // Secondary no-fault, RO
1998
    case 0x8a: // Primary no-fault LE, RO
1999
    case 0x8b: // Secondary no-fault LE, RO
2000
    default:
2001
        do_unassigned_access(addr, 1, 0, 1);
2002
        return;
2003
    }
2004
}
2005
#endif /* CONFIG_USER_ONLY */
2006

    
2007
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
2008
{
2009
    unsigned int i;
2010
    target_ulong val;
2011

    
2012
    switch (asi) {
2013
    case 0xf0: // Block load primary
2014
    case 0xf1: // Block load secondary
2015
    case 0xf8: // Block load primary LE
2016
    case 0xf9: // Block load secondary LE
2017
        if (rd & 7) {
2018
            raise_exception(TT_ILL_INSN);
2019
            return;
2020
        }
2021
        if (addr & 0x3f) {
2022
            raise_exception(TT_UNALIGNED);
2023
            return;
2024
        }
2025
        for (i = 0; i < 16; i++) {
2026
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
2027
            addr += 4;
2028
        }
2029

    
2030
        return;
2031
    default:
2032
        break;
2033
    }
2034

    
2035
    val = helper_ld_asi(addr, asi, size, 0);
2036
    switch(size) {
2037
    default:
2038
    case 4:
2039
        *((uint32_t *)&FT0) = val;
2040
        break;
2041
    case 8:
2042
        *((int64_t *)&DT0) = val;
2043
        break;
2044
    case 16:
2045
        // XXX
2046
        break;
2047
    }
2048
}
2049

    
2050
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
2051
{
2052
    unsigned int i;
2053
    target_ulong val = 0;
2054

    
2055
    switch (asi) {
2056
    case 0xf0: // Block store primary
2057
    case 0xf1: // Block store secondary
2058
    case 0xf8: // Block store primary LE
2059
    case 0xf9: // Block store secondary LE
2060
        if (rd & 7) {
2061
            raise_exception(TT_ILL_INSN);
2062
            return;
2063
        }
2064
        if (addr & 0x3f) {
2065
            raise_exception(TT_UNALIGNED);
2066
            return;
2067
        }
2068
        for (i = 0; i < 16; i++) {
2069
            val = *(uint32_t *)&env->fpr[rd++];
2070
            helper_st_asi(addr, val, asi & 0x8f, 4);
2071
            addr += 4;
2072
        }
2073

    
2074
        return;
2075
    default:
2076
        break;
2077
    }
2078

    
2079
    switch(size) {
2080
    default:
2081
    case 4:
2082
        val = *((uint32_t *)&FT0);
2083
        break;
2084
    case 8:
2085
        val = *((int64_t *)&DT0);
2086
        break;
2087
    case 16:
2088
        // XXX
2089
        break;
2090
    }
2091
    helper_st_asi(addr, val, asi, size);
2092
}
2093

    
2094
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2095
                            target_ulong val2, uint32_t asi)
2096
{
2097
    target_ulong ret;
2098

    
2099
    val1 &= 0xffffffffUL;
2100
    ret = helper_ld_asi(addr, asi, 4, 0);
2101
    ret &= 0xffffffffUL;
2102
    if (val1 == ret)
2103
        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2104
    return ret;
2105
}
2106

    
2107
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2108
                             target_ulong val2, uint32_t asi)
2109
{
2110
    target_ulong ret;
2111

    
2112
    ret = helper_ld_asi(addr, asi, 8, 0);
2113
    if (val1 == ret)
2114
        helper_st_asi(addr, val2, asi, 8);
2115
    return ret;
2116
}
2117
#endif /* TARGET_SPARC64 */
2118

    
2119
#ifndef TARGET_SPARC64
2120
void helper_rett(void)
2121
{
2122
    unsigned int cwp;
2123

    
2124
    if (env->psret == 1)
2125
        raise_exception(TT_ILL_INSN);
2126

    
2127
    env->psret = 1;
2128
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2129
    if (env->wim & (1 << cwp)) {
2130
        raise_exception(TT_WIN_UNF);
2131
    }
2132
    set_cwp(cwp);
2133
    env->psrs = env->psrps;
2134
}
2135
#endif
2136

    
2137
target_ulong helper_udiv(target_ulong a, target_ulong b)
2138
{
2139
    uint64_t x0;
2140
    uint32_t x1;
2141

    
2142
    x0 = a | ((uint64_t) (env->y) << 32);
2143
    x1 = b;
2144

    
2145
    if (x1 == 0) {
2146
        raise_exception(TT_DIV_ZERO);
2147
    }
2148

    
2149
    x0 = x0 / x1;
2150
    if (x0 > 0xffffffff) {
2151
        env->cc_src2 = 1;
2152
        return 0xffffffff;
2153
    } else {
2154
        env->cc_src2 = 0;
2155
        return x0;
2156
    }
2157
}
2158

    
2159
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2160
{
2161
    int64_t x0;
2162
    int32_t x1;
2163

    
2164
    x0 = a | ((int64_t) (env->y) << 32);
2165
    x1 = b;
2166

    
2167
    if (x1 == 0) {
2168
        raise_exception(TT_DIV_ZERO);
2169
    }
2170

    
2171
    x0 = x0 / x1;
2172
    if ((int32_t) x0 != x0) {
2173
        env->cc_src2 = 1;
2174
        return x0 < 0? 0x80000000: 0x7fffffff;
2175
    } else {
2176
        env->cc_src2 = 0;
2177
        return x0;
2178
    }
2179
}
2180

    
2181
uint64_t helper_pack64(target_ulong high, target_ulong low)
2182
{
2183
    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2184
}
2185

    
2186
#ifdef TARGET_ABI32
2187
#define ADDR(x) ((x) & 0xffffffff)
2188
#else
2189
#define ADDR(x) (x)
2190
#endif
2191

    
2192
void helper_stdf(target_ulong addr, int mem_idx)
2193
{
2194
#if !defined(CONFIG_USER_ONLY)
2195
    switch (mem_idx) {
2196
    case 0:
2197
        stfq_user(ADDR(addr), DT0);
2198
        break;
2199
    case 1:
2200
        stfq_kernel(ADDR(addr), DT0);
2201
        break;
2202
#ifdef TARGET_SPARC64
2203
    case 2:
2204
        stfq_hypv(ADDR(addr), DT0);
2205
        break;
2206
#endif
2207
    default:
2208
        break;
2209
    }
2210
#else
2211
    stfq_raw(ADDR(addr), DT0);
2212
#endif
2213
}
2214

    
2215
void helper_lddf(target_ulong addr, int mem_idx)
2216
{
2217
#if !defined(CONFIG_USER_ONLY)
2218
    switch (mem_idx) {
2219
    case 0:
2220
        DT0 = ldfq_user(ADDR(addr));
2221
        break;
2222
    case 1:
2223
        DT0 = ldfq_kernel(ADDR(addr));
2224
        break;
2225
#ifdef TARGET_SPARC64
2226
    case 2:
2227
        DT0 = ldfq_hypv(ADDR(addr));
2228
        break;
2229
#endif
2230
    default:
2231
        break;
2232
    }
2233
#else
2234
    DT0 = ldfq_raw(ADDR(addr));
2235
#endif
2236
}
2237

    
2238
void helper_ldqf(target_ulong addr, int mem_idx)
2239
{
2240
    // XXX add 128 bit load
2241
    CPU_QuadU u;
2242

    
2243
#if !defined(CONFIG_USER_ONLY)
2244
    switch (mem_idx) {
2245
    case 0:
2246
        u.ll.upper = ldq_user(ADDR(addr));
2247
        u.ll.lower = ldq_user(ADDR(addr + 8));
2248
        QT0 = u.q;
2249
        break;
2250
    case 1:
2251
        u.ll.upper = ldq_kernel(ADDR(addr));
2252
        u.ll.lower = ldq_kernel(ADDR(addr + 8));
2253
        QT0 = u.q;
2254
        break;
2255
#ifdef TARGET_SPARC64
2256
    case 2:
2257
        u.ll.upper = ldq_hypv(ADDR(addr));
2258
        u.ll.lower = ldq_hypv(ADDR(addr + 8));
2259
        QT0 = u.q;
2260
        break;
2261
#endif
2262
    default:
2263
        break;
2264
    }
2265
#else
2266
    u.ll.upper = ldq_raw(ADDR(addr));
2267
    u.ll.lower = ldq_raw(ADDR(addr + 8));
2268
    QT0 = u.q;
2269
#endif
2270
}
2271

    
2272
void helper_stqf(target_ulong addr, int mem_idx)
2273
{
2274
    // XXX add 128 bit store
2275
    CPU_QuadU u;
2276

    
2277
#if !defined(CONFIG_USER_ONLY)
2278
    switch (mem_idx) {
2279
    case 0:
2280
        u.q = QT0;
2281
        stq_user(ADDR(addr), u.ll.upper);
2282
        stq_user(ADDR(addr + 8), u.ll.lower);
2283
        break;
2284
    case 1:
2285
        u.q = QT0;
2286
        stq_kernel(ADDR(addr), u.ll.upper);
2287
        stq_kernel(ADDR(addr + 8), u.ll.lower);
2288
        break;
2289
#ifdef TARGET_SPARC64
2290
    case 2:
2291
        u.q = QT0;
2292
        stq_hypv(ADDR(addr), u.ll.upper);
2293
        stq_hypv(ADDR(addr + 8), u.ll.lower);
2294
        break;
2295
#endif
2296
    default:
2297
        break;
2298
    }
2299
#else
2300
    u.q = QT0;
2301
    stq_raw(ADDR(addr), u.ll.upper);
2302
    stq_raw(ADDR(addr + 8), u.ll.lower);
2303
#endif
2304
}
2305

    
2306
#undef ADDR
2307

    
2308
void helper_ldfsr(void)
2309
{
2310
    int rnd_mode;
2311

    
2312
    PUT_FSR32(env, *((uint32_t *) &FT0));
2313
    switch (env->fsr & FSR_RD_MASK) {
2314
    case FSR_RD_NEAREST:
2315
        rnd_mode = float_round_nearest_even;
2316
        break;
2317
    default:
2318
    case FSR_RD_ZERO:
2319
        rnd_mode = float_round_to_zero;
2320
        break;
2321
    case FSR_RD_POS:
2322
        rnd_mode = float_round_up;
2323
        break;
2324
    case FSR_RD_NEG:
2325
        rnd_mode = float_round_down;
2326
        break;
2327
    }
2328
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2329
}
2330

    
2331
void helper_stfsr(void)
2332
{
2333
    *((uint32_t *) &FT0) = GET_FSR32(env);
2334
}
2335

    
2336
void helper_debug(void)
2337
{
2338
    env->exception_index = EXCP_DEBUG;
2339
    cpu_loop_exit();
2340
}
2341

    
2342
#ifndef TARGET_SPARC64
2343
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2344
   handling ? */
2345
void helper_save(void)
2346
{
2347
    uint32_t cwp;
2348

    
2349
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2350
    if (env->wim & (1 << cwp)) {
2351
        raise_exception(TT_WIN_OVF);
2352
    }
2353
    set_cwp(cwp);
2354
}
2355

    
2356
void helper_restore(void)
2357
{
2358
    uint32_t cwp;
2359

    
2360
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2361
    if (env->wim & (1 << cwp)) {
2362
        raise_exception(TT_WIN_UNF);
2363
    }
2364
    set_cwp(cwp);
2365
}
2366

    
2367
void helper_wrpsr(target_ulong new_psr)
2368
{
2369
    if ((new_psr & PSR_CWP) >= NWINDOWS)
2370
        raise_exception(TT_ILL_INSN);
2371
    else
2372
        PUT_PSR(env, new_psr);
2373
}
2374

    
2375
target_ulong helper_rdpsr(void)
2376
{
2377
    return GET_PSR(env);
2378
}
2379

    
2380
#else
2381
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2382
   handling ? */
2383
void helper_save(void)
2384
{
2385
    uint32_t cwp;
2386

    
2387
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2388
    if (env->cansave == 0) {
2389
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2390
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2391
                                    ((env->wstate & 0x7) << 2)));
2392
    } else {
2393
        if (env->cleanwin - env->canrestore == 0) {
2394
            // XXX Clean windows without trap
2395
            raise_exception(TT_CLRWIN);
2396
        } else {
2397
            env->cansave--;
2398
            env->canrestore++;
2399
            set_cwp(cwp);
2400
        }
2401
    }
2402
}
2403

    
2404
void helper_restore(void)
2405
{
2406
    uint32_t cwp;
2407

    
2408
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2409
    if (env->canrestore == 0) {
2410
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2411
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2412
                                   ((env->wstate & 0x7) << 2)));
2413
    } else {
2414
        env->cansave++;
2415
        env->canrestore--;
2416
        set_cwp(cwp);
2417
    }
2418
}
2419

    
2420
void helper_flushw(void)
2421
{
2422
    if (env->cansave != NWINDOWS - 2) {
2423
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2424
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2425
                                    ((env->wstate & 0x7) << 2)));
2426
    }
2427
}
2428

    
2429
void helper_saved(void)
2430
{
2431
    env->cansave++;
2432
    if (env->otherwin == 0)
2433
        env->canrestore--;
2434
    else
2435
        env->otherwin--;
2436
}
2437

    
2438
void helper_restored(void)
2439
{
2440
    env->canrestore++;
2441
    if (env->cleanwin < NWINDOWS - 1)
2442
        env->cleanwin++;
2443
    if (env->otherwin == 0)
2444
        env->cansave--;
2445
    else
2446
        env->otherwin--;
2447
}
2448

    
2449
target_ulong helper_rdccr(void)
2450
{
2451
    return GET_CCR(env);
2452
}
2453

    
2454
void helper_wrccr(target_ulong new_ccr)
2455
{
2456
    PUT_CCR(env, new_ccr);
2457
}
2458

    
2459
// CWP handling is reversed in V9, but we still use the V8 register
2460
// order.
2461
target_ulong helper_rdcwp(void)
2462
{
2463
    return GET_CWP64(env);
2464
}
2465

    
2466
void helper_wrcwp(target_ulong new_cwp)
2467
{
2468
    PUT_CWP64(env, new_cwp);
2469
}
2470

    
2471
// This function uses non-native bit order
2472
#define GET_FIELD(X, FROM, TO)                                  \
2473
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2474

    
2475
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2476
#define GET_FIELD_SP(X, FROM, TO)               \
2477
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2478

    
2479
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2480
{
2481
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2482
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2483
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2484
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2485
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2486
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2487
        (((pixel_addr >> 55) & 1) << 4) |
2488
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2489
        GET_FIELD_SP(pixel_addr, 11, 12);
2490
}
2491

    
2492
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2493
{
2494
    uint64_t tmp;
2495

    
2496
    tmp = addr + offset;
2497
    env->gsr &= ~7ULL;
2498
    env->gsr |= tmp & 7ULL;
2499
    return tmp & ~7ULL;
2500
}
2501

    
2502
target_ulong helper_popc(target_ulong val)
2503
{
2504
    return ctpop64(val);
2505
}
2506

    
2507
static inline uint64_t *get_gregset(uint64_t pstate)
2508
{
2509
    switch (pstate) {
2510
    default:
2511
    case 0:
2512
        return env->bgregs;
2513
    case PS_AG:
2514
        return env->agregs;
2515
    case PS_MG:
2516
        return env->mgregs;
2517
    case PS_IG:
2518
        return env->igregs;
2519
    }
2520
}
2521

    
2522
static inline void change_pstate(uint64_t new_pstate)
2523
{
2524
    uint64_t pstate_regs, new_pstate_regs;
2525
    uint64_t *src, *dst;
2526

    
2527
    pstate_regs = env->pstate & 0xc01;
2528
    new_pstate_regs = new_pstate & 0xc01;
2529
    if (new_pstate_regs != pstate_regs) {
2530
        // Switch global register bank
2531
        src = get_gregset(new_pstate_regs);
2532
        dst = get_gregset(pstate_regs);
2533
        memcpy32(dst, env->gregs);
2534
        memcpy32(env->gregs, src);
2535
    }
2536
    env->pstate = new_pstate;
2537
}
2538

    
2539
void helper_wrpstate(target_ulong new_state)
2540
{
2541
    change_pstate(new_state & 0xf3f);
2542
}
2543

    
2544
void helper_done(void)
2545
{
2546
    env->tl--;
2547
    env->tsptr = &env->ts[env->tl];
2548
    env->pc = env->tsptr->tpc;
2549
    env->npc = env->tsptr->tnpc + 4;
2550
    PUT_CCR(env, env->tsptr->tstate >> 32);
2551
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2552
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2553
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2554
}
2555

    
2556
void helper_retry(void)
2557
{
2558
    env->tl--;
2559
    env->tsptr = &env->ts[env->tl];
2560
    env->pc = env->tsptr->tpc;
2561
    env->npc = env->tsptr->tnpc;
2562
    PUT_CCR(env, env->tsptr->tstate >> 32);
2563
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2564
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2565
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2566
}
2567
#endif
2568

    
2569
void set_cwp(int new_cwp)
2570
{
2571
    /* put the modified wrap registers at their proper location */
2572
    if (env->cwp == (NWINDOWS - 1))
2573
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2574
    env->cwp = new_cwp;
2575
    /* put the wrap registers at their temporary location */
2576
    if (new_cwp == (NWINDOWS - 1))
2577
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2578
    env->regwptr = env->regbase + (new_cwp * 16);
2579
    REGWPTR = env->regwptr;
2580
}
2581

    
2582
void cpu_set_cwp(CPUState *env1, int new_cwp)
2583
{
2584
    CPUState *saved_env;
2585
#ifdef reg_REGWPTR
2586
    target_ulong *saved_regwptr;
2587
#endif
2588

    
2589
    saved_env = env;
2590
#ifdef reg_REGWPTR
2591
    saved_regwptr = REGWPTR;
2592
#endif
2593
    env = env1;
2594
    set_cwp(new_cwp);
2595
    env = saved_env;
2596
#ifdef reg_REGWPTR
2597
    REGWPTR = saved_regwptr;
2598
#endif
2599
}
2600

    
2601
#ifdef TARGET_SPARC64
2602
#ifdef DEBUG_PCALL
2603
static const char * const excp_names[0x50] = {
2604
    [TT_TFAULT] = "Instruction Access Fault",
2605
    [TT_TMISS] = "Instruction Access MMU Miss",
2606
    [TT_CODE_ACCESS] = "Instruction Access Error",
2607
    [TT_ILL_INSN] = "Illegal Instruction",
2608
    [TT_PRIV_INSN] = "Privileged Instruction",
2609
    [TT_NFPU_INSN] = "FPU Disabled",
2610
    [TT_FP_EXCP] = "FPU Exception",
2611
    [TT_TOVF] = "Tag Overflow",
2612
    [TT_CLRWIN] = "Clean Windows",
2613
    [TT_DIV_ZERO] = "Division By Zero",
2614
    [TT_DFAULT] = "Data Access Fault",
2615
    [TT_DMISS] = "Data Access MMU Miss",
2616
    [TT_DATA_ACCESS] = "Data Access Error",
2617
    [TT_DPROT] = "Data Protection Error",
2618
    [TT_UNALIGNED] = "Unaligned Memory Access",
2619
    [TT_PRIV_ACT] = "Privileged Action",
2620
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2621
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2622
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2623
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2624
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2625
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2626
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2627
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2628
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2629
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2630
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2631
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2632
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2633
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2634
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2635
};
2636
#endif
2637

    
2638
void do_interrupt(int intno)
2639
{
2640
#ifdef DEBUG_PCALL
2641
    if (loglevel & CPU_LOG_INT) {
2642
        static int count;
2643
        const char *name;
2644

    
2645
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2646
            name = "Unknown";
2647
        else if (intno >= 0x100)
2648
            name = "Trap Instruction";
2649
        else if (intno >= 0xc0)
2650
            name = "Window Fill";
2651
        else if (intno >= 0x80)
2652
            name = "Window Spill";
2653
        else {
2654
            name = excp_names[intno];
2655
            if (!name)
2656
                name = "Unknown";
2657
        }
2658

    
2659
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2660
                " SP=%016" PRIx64 "\n",
2661
                count, name, intno,
2662
                env->pc,
2663
                env->npc, env->regwptr[6]);
2664
        cpu_dump_state(env, logfile, fprintf, 0);
2665
#if 0
2666
        {
2667
            int i;
2668
            uint8_t *ptr;
2669

2670
            fprintf(logfile, "       code=");
2671
            ptr = (uint8_t *)env->pc;
2672
            for(i = 0; i < 16; i++) {
2673
                fprintf(logfile, " %02x", ldub(ptr + i));
2674
            }
2675
            fprintf(logfile, "\n");
2676
        }
2677
#endif
2678
        count++;
2679
    }
2680
#endif
2681
#if !defined(CONFIG_USER_ONLY)
2682
    if (env->tl == MAXTL) {
2683
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
2684
        return;
2685
    }
2686
#endif
2687
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2688
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2689
        GET_CWP64(env);
2690
    env->tsptr->tpc = env->pc;
2691
    env->tsptr->tnpc = env->npc;
2692
    env->tsptr->tt = intno;
2693
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
2694

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

    
2751
void do_interrupt(int intno)
2752
{
2753
    int cwp;
2754

    
2755
#ifdef DEBUG_PCALL
2756
    if (loglevel & CPU_LOG_INT) {
2757
        static int count;
2758
        const char *name;
2759

    
2760
        if (intno < 0 || intno >= 0x100)
2761
            name = "Unknown";
2762
        else if (intno >= 0x80)
2763
            name = "Trap Instruction";
2764
        else {
2765
            name = excp_names[intno];
2766
            if (!name)
2767
                name = "Unknown";
2768
        }
2769

    
2770
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2771
                count, name, intno,
2772
                env->pc,
2773
                env->npc, env->regwptr[6]);
2774
        cpu_dump_state(env, logfile, fprintf, 0);
2775
#if 0
2776
        {
2777
            int i;
2778
            uint8_t *ptr;
2779

2780
            fprintf(logfile, "       code=");
2781
            ptr = (uint8_t *)env->pc;
2782
            for(i = 0; i < 16; i++) {
2783
                fprintf(logfile, " %02x", ldub(ptr + i));
2784
            }
2785
            fprintf(logfile, "\n");
2786
        }
2787
#endif
2788
        count++;
2789
    }
2790
#endif
2791
#if !defined(CONFIG_USER_ONLY)
2792
    if (env->psret == 0) {
2793
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
2794
        return;
2795
    }
2796
#endif
2797
    env->psret = 0;
2798
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2799
    set_cwp(cwp);
2800
    env->regwptr[9] = env->pc;
2801
    env->regwptr[10] = env->npc;
2802
    env->psrps = env->psrs;
2803
    env->psrs = 1;
2804
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2805
    env->pc = env->tbr;
2806
    env->npc = env->pc + 4;
2807
    env->exception_index = 0;
2808
}
2809
#endif
2810

    
2811
#if !defined(CONFIG_USER_ONLY)
2812

    
2813
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2814
                                void *retaddr);
2815

    
2816
#define MMUSUFFIX _mmu
2817
#define ALIGNED_ONLY
2818
#ifdef __s390__
2819
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2820
#else
2821
# define GETPC() (__builtin_return_address(0))
2822
#endif
2823

    
2824
#define SHIFT 0
2825
#include "softmmu_template.h"
2826

    
2827
#define SHIFT 1
2828
#include "softmmu_template.h"
2829

    
2830
#define SHIFT 2
2831
#include "softmmu_template.h"
2832

    
2833
#define SHIFT 3
2834
#include "softmmu_template.h"
2835

    
2836
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2837
                                void *retaddr)
2838
{
2839
#ifdef DEBUG_UNALIGNED
2840
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
2841
#endif
2842
    raise_exception(TT_UNALIGNED);
2843
}
2844

    
2845
/* try to fill the TLB and return an exception if error. If retaddr is
2846
   NULL, it means that the function was called in C code (i.e. not
2847
   from generated code or from helper.c) */
2848
/* XXX: fix it to restore all registers */
2849
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2850
{
2851
    TranslationBlock *tb;
2852
    int ret;
2853
    unsigned long pc;
2854
    CPUState *saved_env;
2855

    
2856
    /* XXX: hack to restore env in all cases, even if not called from
2857
       generated code */
2858
    saved_env = env;
2859
    env = cpu_single_env;
2860

    
2861
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2862
    if (ret) {
2863
        if (retaddr) {
2864
            /* now we have a real cpu fault */
2865
            pc = (unsigned long)retaddr;
2866
            tb = tb_find_pc(pc);
2867
            if (tb) {
2868
                /* the PC is inside the translated code. It means that we have
2869
                   a virtual CPU fault */
2870
                cpu_restore_state(tb, env, pc, (void *)env->cond);
2871
            }
2872
        }
2873
        cpu_loop_exit();
2874
    }
2875
    env = saved_env;
2876
}
2877

    
2878
#endif
2879

    
2880
#ifndef TARGET_SPARC64
2881
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2882
                          int is_asi)
2883
{
2884
    CPUState *saved_env;
2885

    
2886
    /* XXX: hack to restore env in all cases, even if not called from
2887
       generated code */
2888
    saved_env = env;
2889
    env = cpu_single_env;
2890
#ifdef DEBUG_UNASSIGNED
2891
    if (is_asi)
2892
        printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2893
               TARGET_FMT_lx "\n",
2894
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2895
               env->pc);
2896
    else
2897
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2898
               TARGET_FMT_lx "\n",
2899
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2900
#endif
2901
    if (env->mmuregs[3]) /* Fault status register */
2902
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2903
    if (is_asi)
2904
        env->mmuregs[3] |= 1 << 16;
2905
    if (env->psrs)
2906
        env->mmuregs[3] |= 1 << 5;
2907
    if (is_exec)
2908
        env->mmuregs[3] |= 1 << 6;
2909
    if (is_write)
2910
        env->mmuregs[3] |= 1 << 7;
2911
    env->mmuregs[3] |= (5 << 2) | 2;
2912
    env->mmuregs[4] = addr; /* Fault address register */
2913
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2914
        if (is_exec)
2915
            raise_exception(TT_CODE_ACCESS);
2916
        else
2917
            raise_exception(TT_DATA_ACCESS);
2918
    }
2919
    env = saved_env;
2920
}
2921
#else
2922
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2923
                          int is_asi)
2924
{
2925
#ifdef DEBUG_UNASSIGNED
2926
    CPUState *saved_env;
2927

    
2928
    /* XXX: hack to restore env in all cases, even if not called from
2929
       generated code */
2930
    saved_env = env;
2931
    env = cpu_single_env;
2932
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2933
           addr, env->pc);
2934
    env = saved_env;
2935
#endif
2936
    if (is_exec)
2937
        raise_exception(TT_CODE_ACCESS);
2938
    else
2939
        raise_exception(TT_DATA_ACCESS);
2940
}
2941
#endif
2942