Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 22548760

History | View | Annotate | Download (79.9 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
#ifdef __i386__
2193
void helper_std_i386(target_ulong addr, int mem_idx)
2194
{
2195
    uint64_t tmp = ((uint64_t)env->t1 << 32) | (uint64_t)(env->t2 & 0xffffffff);
2196

    
2197
#if !defined(CONFIG_USER_ONLY)
2198
    switch (mem_idx) {
2199
    case 0:
2200
        stq_user(ADDR(addr), tmp);
2201
        break;
2202
    case 1:
2203
        stq_kernel(ADDR(addr), tmp);
2204
        break;
2205
#ifdef TARGET_SPARC64
2206
    case 2:
2207
        stq_hypv(ADDR(addr), tmp);
2208
        break;
2209
#endif
2210
    default:
2211
        break;
2212
    }
2213
#else
2214
    stq_raw(ADDR(addr), tmp);
2215
#endif
2216
}
2217
#endif /* __i386__ */
2218

    
2219
void helper_stdf(target_ulong addr, int mem_idx)
2220
{
2221
#if !defined(CONFIG_USER_ONLY)
2222
    switch (mem_idx) {
2223
    case 0:
2224
        stfq_user(ADDR(addr), DT0);
2225
        break;
2226
    case 1:
2227
        stfq_kernel(ADDR(addr), DT0);
2228
        break;
2229
#ifdef TARGET_SPARC64
2230
    case 2:
2231
        stfq_hypv(ADDR(addr), DT0);
2232
        break;
2233
#endif
2234
    default:
2235
        break;
2236
    }
2237
#else
2238
    stfq_raw(ADDR(addr), DT0);
2239
#endif
2240
}
2241

    
2242
void helper_lddf(target_ulong addr, int mem_idx)
2243
{
2244
#if !defined(CONFIG_USER_ONLY)
2245
    switch (mem_idx) {
2246
    case 0:
2247
        DT0 = ldfq_user(ADDR(addr));
2248
        break;
2249
    case 1:
2250
        DT0 = ldfq_kernel(ADDR(addr));
2251
        break;
2252
#ifdef TARGET_SPARC64
2253
    case 2:
2254
        DT0 = ldfq_hypv(ADDR(addr));
2255
        break;
2256
#endif
2257
    default:
2258
        break;
2259
    }
2260
#else
2261
    DT0 = ldfq_raw(ADDR(addr));
2262
#endif
2263
}
2264

    
2265
void helper_ldqf(target_ulong addr, int mem_idx)
2266
{
2267
    // XXX add 128 bit load
2268
    CPU_QuadU u;
2269

    
2270
#if !defined(CONFIG_USER_ONLY)
2271
    switch (mem_idx) {
2272
    case 0:
2273
        u.ll.upper = ldq_user(ADDR(addr));
2274
        u.ll.lower = ldq_user(ADDR(addr + 8));
2275
        QT0 = u.q;
2276
        break;
2277
    case 1:
2278
        u.ll.upper = ldq_kernel(ADDR(addr));
2279
        u.ll.lower = ldq_kernel(ADDR(addr + 8));
2280
        QT0 = u.q;
2281
        break;
2282
#ifdef TARGET_SPARC64
2283
    case 2:
2284
        u.ll.upper = ldq_hypv(ADDR(addr));
2285
        u.ll.lower = ldq_hypv(ADDR(addr + 8));
2286
        QT0 = u.q;
2287
        break;
2288
#endif
2289
    default:
2290
        break;
2291
    }
2292
#else
2293
    u.ll.upper = ldq_raw(ADDR(addr));
2294
    u.ll.lower = ldq_raw(ADDR(addr + 8));
2295
    QT0 = u.q;
2296
#endif
2297
}
2298

    
2299
void helper_stqf(target_ulong addr, int mem_idx)
2300
{
2301
    // XXX add 128 bit store
2302
    CPU_QuadU u;
2303

    
2304
#if !defined(CONFIG_USER_ONLY)
2305
    switch (mem_idx) {
2306
    case 0:
2307
        u.q = QT0;
2308
        stq_user(ADDR(addr), u.ll.upper);
2309
        stq_user(ADDR(addr + 8), u.ll.lower);
2310
        break;
2311
    case 1:
2312
        u.q = QT0;
2313
        stq_kernel(ADDR(addr), u.ll.upper);
2314
        stq_kernel(ADDR(addr + 8), u.ll.lower);
2315
        break;
2316
#ifdef TARGET_SPARC64
2317
    case 2:
2318
        u.q = QT0;
2319
        stq_hypv(ADDR(addr), u.ll.upper);
2320
        stq_hypv(ADDR(addr + 8), u.ll.lower);
2321
        break;
2322
#endif
2323
    default:
2324
        break;
2325
    }
2326
#else
2327
    u.q = QT0;
2328
    stq_raw(ADDR(addr), u.ll.upper);
2329
    stq_raw(ADDR(addr + 8), u.ll.lower);
2330
#endif
2331
}
2332

    
2333
#undef ADDR
2334

    
2335
void helper_ldfsr(void)
2336
{
2337
    int rnd_mode;
2338

    
2339
    PUT_FSR32(env, *((uint32_t *) &FT0));
2340
    switch (env->fsr & FSR_RD_MASK) {
2341
    case FSR_RD_NEAREST:
2342
        rnd_mode = float_round_nearest_even;
2343
        break;
2344
    default:
2345
    case FSR_RD_ZERO:
2346
        rnd_mode = float_round_to_zero;
2347
        break;
2348
    case FSR_RD_POS:
2349
        rnd_mode = float_round_up;
2350
        break;
2351
    case FSR_RD_NEG:
2352
        rnd_mode = float_round_down;
2353
        break;
2354
    }
2355
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2356
}
2357

    
2358
void helper_stfsr(void)
2359
{
2360
    *((uint32_t *) &FT0) = GET_FSR32(env);
2361
}
2362

    
2363
void helper_debug(void)
2364
{
2365
    env->exception_index = EXCP_DEBUG;
2366
    cpu_loop_exit();
2367
}
2368

    
2369
#ifndef TARGET_SPARC64
2370
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2371
   handling ? */
2372
void helper_save(void)
2373
{
2374
    uint32_t cwp;
2375

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

    
2383
void helper_restore(void)
2384
{
2385
    uint32_t cwp;
2386

    
2387
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2388
    if (env->wim & (1 << cwp)) {
2389
        raise_exception(TT_WIN_UNF);
2390
    }
2391
    set_cwp(cwp);
2392
}
2393

    
2394
void helper_wrpsr(target_ulong new_psr)
2395
{
2396
    if ((new_psr & PSR_CWP) >= NWINDOWS)
2397
        raise_exception(TT_ILL_INSN);
2398
    else
2399
        PUT_PSR(env, new_psr);
2400
}
2401

    
2402
target_ulong helper_rdpsr(void)
2403
{
2404
    return GET_PSR(env);
2405
}
2406

    
2407
#else
2408
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2409
   handling ? */
2410
void helper_save(void)
2411
{
2412
    uint32_t cwp;
2413

    
2414
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2415
    if (env->cansave == 0) {
2416
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2417
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2418
                                    ((env->wstate & 0x7) << 2)));
2419
    } else {
2420
        if (env->cleanwin - env->canrestore == 0) {
2421
            // XXX Clean windows without trap
2422
            raise_exception(TT_CLRWIN);
2423
        } else {
2424
            env->cansave--;
2425
            env->canrestore++;
2426
            set_cwp(cwp);
2427
        }
2428
    }
2429
}
2430

    
2431
void helper_restore(void)
2432
{
2433
    uint32_t cwp;
2434

    
2435
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2436
    if (env->canrestore == 0) {
2437
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2438
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2439
                                   ((env->wstate & 0x7) << 2)));
2440
    } else {
2441
        env->cansave++;
2442
        env->canrestore--;
2443
        set_cwp(cwp);
2444
    }
2445
}
2446

    
2447
void helper_flushw(void)
2448
{
2449
    if (env->cansave != NWINDOWS - 2) {
2450
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2451
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2452
                                    ((env->wstate & 0x7) << 2)));
2453
    }
2454
}
2455

    
2456
void helper_saved(void)
2457
{
2458
    env->cansave++;
2459
    if (env->otherwin == 0)
2460
        env->canrestore--;
2461
    else
2462
        env->otherwin--;
2463
}
2464

    
2465
void helper_restored(void)
2466
{
2467
    env->canrestore++;
2468
    if (env->cleanwin < NWINDOWS - 1)
2469
        env->cleanwin++;
2470
    if (env->otherwin == 0)
2471
        env->cansave--;
2472
    else
2473
        env->otherwin--;
2474
}
2475

    
2476
target_ulong helper_rdccr(void)
2477
{
2478
    return GET_CCR(env);
2479
}
2480

    
2481
void helper_wrccr(target_ulong new_ccr)
2482
{
2483
    PUT_CCR(env, new_ccr);
2484
}
2485

    
2486
// CWP handling is reversed in V9, but we still use the V8 register
2487
// order.
2488
target_ulong helper_rdcwp(void)
2489
{
2490
    return GET_CWP64(env);
2491
}
2492

    
2493
void helper_wrcwp(target_ulong new_cwp)
2494
{
2495
    PUT_CWP64(env, new_cwp);
2496
}
2497

    
2498
// This function uses non-native bit order
2499
#define GET_FIELD(X, FROM, TO)                                  \
2500
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2501

    
2502
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2503
#define GET_FIELD_SP(X, FROM, TO)               \
2504
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2505

    
2506
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2507
{
2508
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2509
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2510
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2511
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2512
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2513
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2514
        (((pixel_addr >> 55) & 1) << 4) |
2515
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2516
        GET_FIELD_SP(pixel_addr, 11, 12);
2517
}
2518

    
2519
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2520
{
2521
    uint64_t tmp;
2522

    
2523
    tmp = addr + offset;
2524
    env->gsr &= ~7ULL;
2525
    env->gsr |= tmp & 7ULL;
2526
    return tmp & ~7ULL;
2527
}
2528

    
2529
target_ulong helper_popc(target_ulong val)
2530
{
2531
    return ctpop64(val);
2532
}
2533

    
2534
static inline uint64_t *get_gregset(uint64_t pstate)
2535
{
2536
    switch (pstate) {
2537
    default:
2538
    case 0:
2539
        return env->bgregs;
2540
    case PS_AG:
2541
        return env->agregs;
2542
    case PS_MG:
2543
        return env->mgregs;
2544
    case PS_IG:
2545
        return env->igregs;
2546
    }
2547
}
2548

    
2549
static inline void change_pstate(uint64_t new_pstate)
2550
{
2551
    uint64_t pstate_regs, new_pstate_regs;
2552
    uint64_t *src, *dst;
2553

    
2554
    pstate_regs = env->pstate & 0xc01;
2555
    new_pstate_regs = new_pstate & 0xc01;
2556
    if (new_pstate_regs != pstate_regs) {
2557
        // Switch global register bank
2558
        src = get_gregset(new_pstate_regs);
2559
        dst = get_gregset(pstate_regs);
2560
        memcpy32(dst, env->gregs);
2561
        memcpy32(env->gregs, src);
2562
    }
2563
    env->pstate = new_pstate;
2564
}
2565

    
2566
void helper_wrpstate(target_ulong new_state)
2567
{
2568
    change_pstate(new_state & 0xf3f);
2569
}
2570

    
2571
void helper_done(void)
2572
{
2573
    env->tl--;
2574
    env->tsptr = &env->ts[env->tl];
2575
    env->pc = env->tsptr->tpc;
2576
    env->npc = env->tsptr->tnpc + 4;
2577
    PUT_CCR(env, env->tsptr->tstate >> 32);
2578
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2579
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2580
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2581
}
2582

    
2583
void helper_retry(void)
2584
{
2585
    env->tl--;
2586
    env->tsptr = &env->ts[env->tl];
2587
    env->pc = env->tsptr->tpc;
2588
    env->npc = env->tsptr->tnpc;
2589
    PUT_CCR(env, env->tsptr->tstate >> 32);
2590
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2591
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2592
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2593
}
2594
#endif
2595

    
2596
void set_cwp(int new_cwp)
2597
{
2598
    /* put the modified wrap registers at their proper location */
2599
    if (env->cwp == (NWINDOWS - 1))
2600
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2601
    env->cwp = new_cwp;
2602
    /* put the wrap registers at their temporary location */
2603
    if (new_cwp == (NWINDOWS - 1))
2604
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2605
    env->regwptr = env->regbase + (new_cwp * 16);
2606
    REGWPTR = env->regwptr;
2607
}
2608

    
2609
void cpu_set_cwp(CPUState *env1, int new_cwp)
2610
{
2611
    CPUState *saved_env;
2612
#ifdef reg_REGWPTR
2613
    target_ulong *saved_regwptr;
2614
#endif
2615

    
2616
    saved_env = env;
2617
#ifdef reg_REGWPTR
2618
    saved_regwptr = REGWPTR;
2619
#endif
2620
    env = env1;
2621
    set_cwp(new_cwp);
2622
    env = saved_env;
2623
#ifdef reg_REGWPTR
2624
    REGWPTR = saved_regwptr;
2625
#endif
2626
}
2627

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

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

    
2672
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2673
            name = "Unknown";
2674
        else if (intno >= 0x100)
2675
            name = "Trap Instruction";
2676
        else if (intno >= 0xc0)
2677
            name = "Window Fill";
2678
        else if (intno >= 0x80)
2679
            name = "Window Spill";
2680
        else {
2681
            name = excp_names[intno];
2682
            if (!name)
2683
                name = "Unknown";
2684
        }
2685

    
2686
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2687
                " SP=%016" PRIx64 "\n",
2688
                count, name, intno,
2689
                env->pc,
2690
                env->npc, env->regwptr[6]);
2691
        cpu_dump_state(env, logfile, fprintf, 0);
2692
#if 0
2693
        {
2694
            int i;
2695
            uint8_t *ptr;
2696

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

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

    
2778
void do_interrupt(int intno)
2779
{
2780
    int cwp;
2781

    
2782
#ifdef DEBUG_PCALL
2783
    if (loglevel & CPU_LOG_INT) {
2784
        static int count;
2785
        const char *name;
2786

    
2787
        if (intno < 0 || intno >= 0x100)
2788
            name = "Unknown";
2789
        else if (intno >= 0x80)
2790
            name = "Trap Instruction";
2791
        else {
2792
            name = excp_names[intno];
2793
            if (!name)
2794
                name = "Unknown";
2795
        }
2796

    
2797
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
2798
                count, name, intno,
2799
                env->pc,
2800
                env->npc, env->regwptr[6]);
2801
        cpu_dump_state(env, logfile, fprintf, 0);
2802
#if 0
2803
        {
2804
            int i;
2805
            uint8_t *ptr;
2806

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

    
2838
#if !defined(CONFIG_USER_ONLY)
2839

    
2840
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2841
                                void *retaddr);
2842

    
2843
#define MMUSUFFIX _mmu
2844
#define ALIGNED_ONLY
2845
#ifdef __s390__
2846
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2847
#else
2848
# define GETPC() (__builtin_return_address(0))
2849
#endif
2850

    
2851
#define SHIFT 0
2852
#include "softmmu_template.h"
2853

    
2854
#define SHIFT 1
2855
#include "softmmu_template.h"
2856

    
2857
#define SHIFT 2
2858
#include "softmmu_template.h"
2859

    
2860
#define SHIFT 3
2861
#include "softmmu_template.h"
2862

    
2863
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2864
                                void *retaddr)
2865
{
2866
#ifdef DEBUG_UNALIGNED
2867
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
2868
#endif
2869
    raise_exception(TT_UNALIGNED);
2870
}
2871

    
2872
/* try to fill the TLB and return an exception if error. If retaddr is
2873
   NULL, it means that the function was called in C code (i.e. not
2874
   from generated code or from helper.c) */
2875
/* XXX: fix it to restore all registers */
2876
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2877
{
2878
    TranslationBlock *tb;
2879
    int ret;
2880
    unsigned long pc;
2881
    CPUState *saved_env;
2882

    
2883
    /* XXX: hack to restore env in all cases, even if not called from
2884
       generated code */
2885
    saved_env = env;
2886
    env = cpu_single_env;
2887

    
2888
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2889
    if (ret) {
2890
        if (retaddr) {
2891
            /* now we have a real cpu fault */
2892
            pc = (unsigned long)retaddr;
2893
            tb = tb_find_pc(pc);
2894
            if (tb) {
2895
                /* the PC is inside the translated code. It means that we have
2896
                   a virtual CPU fault */
2897
                cpu_restore_state(tb, env, pc, (void *)T2);
2898
            }
2899
        }
2900
        cpu_loop_exit();
2901
    }
2902
    env = saved_env;
2903
}
2904

    
2905
#endif
2906

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

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

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