Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 25bc827c

History | View | Annotate | Download (75.2 kB)

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

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

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

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

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

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

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

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

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

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

    
61
#define F_BINOP(name)                                           \
62
    F_HELPER(name, s)                                           \
63
    {                                                           \
64
        FT0 = float32_ ## name (FT0, FT1, &env->fp_status);     \
65
    }                                                           \
66
    F_HELPER(name, d)                                           \
67
    {                                                           \
68
        DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
69
    }
70

    
71
F_BINOP(add);
72
F_BINOP(sub);
73
F_BINOP(mul);
74
F_BINOP(div);
75
#undef F_BINOP
76

    
77
void helper_fsmuld(void)
78
{
79
    DT0 = float64_mul(float32_to_float64(FT0, &env->fp_status),
80
                      float32_to_float64(FT1, &env->fp_status),
81
                      &env->fp_status);
82
}
83

    
84
F_HELPER(neg, s)
85
{
86
    FT0 = float32_chs(FT1);
87
}
88

    
89
#ifdef TARGET_SPARC64
90
F_HELPER(neg, d)
91
{
92
    DT0 = float64_chs(DT1);
93
}
94
#endif
95

    
96
/* Integer to float conversion.  */
97
F_HELPER(ito, s)
98
{
99
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
100
}
101

    
102
F_HELPER(ito, d)
103
{
104
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
105
}
106

    
107
#ifdef TARGET_SPARC64
108
F_HELPER(xto, s)
109
{
110
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
111
}
112

    
113
F_HELPER(xto, d)
114
{
115
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
116
}
117
#endif
118
#undef F_HELPER
119

    
120
/* floating point conversion */
121
void helper_fdtos(void)
122
{
123
    FT0 = float64_to_float32(DT1, &env->fp_status);
124
}
125

    
126
void helper_fstod(void)
127
{
128
    DT0 = float32_to_float64(FT1, &env->fp_status);
129
}
130

    
131
/* Float to integer conversion.  */
132
void helper_fstoi(void)
133
{
134
    *((int32_t *)&FT0) = float32_to_int32_round_to_zero(FT1, &env->fp_status);
135
}
136

    
137
void helper_fdtoi(void)
138
{
139
    *((int32_t *)&FT0) = float64_to_int32_round_to_zero(DT1, &env->fp_status);
140
}
141

    
142
#ifdef TARGET_SPARC64
143
void helper_fstox(void)
144
{
145
    *((int64_t *)&DT0) = float32_to_int64_round_to_zero(FT1, &env->fp_status);
146
}
147

    
148
void helper_fdtox(void)
149
{
150
    *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
151
}
152

    
153
void helper_faligndata(void)
154
{
155
    uint64_t tmp;
156

    
157
    tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
158
    tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
159
    *((uint64_t *)&DT0) = tmp;
160
}
161

    
162
void helper_movl_FT0_0(void)
163
{
164
    *((uint32_t *)&FT0) = 0;
165
}
166

    
167
void helper_movl_DT0_0(void)
168
{
169
    *((uint64_t *)&DT0) = 0;
170
}
171

    
172
void helper_movl_FT0_1(void)
173
{
174
    *((uint32_t *)&FT0) = 0xffffffff;
175
}
176

    
177
void helper_movl_DT0_1(void)
178
{
179
    *((uint64_t *)&DT0) = 0xffffffffffffffffULL;
180
}
181

    
182
void helper_fnot(void)
183
{
184
    *(uint64_t *)&DT0 = ~*(uint64_t *)&DT1;
185
}
186

    
187
void helper_fnots(void)
188
{
189
    *(uint32_t *)&FT0 = ~*(uint32_t *)&FT1;
190
}
191

    
192
void helper_fnor(void)
193
{
194
    *(uint64_t *)&DT0 = ~(*(uint64_t *)&DT0 | *(uint64_t *)&DT1);
195
}
196

    
197
void helper_fnors(void)
198
{
199
    *(uint32_t *)&FT0 = ~(*(uint32_t *)&FT0 | *(uint32_t *)&FT1);
200
}
201

    
202
void helper_for(void)
203
{
204
    *(uint64_t *)&DT0 |= *(uint64_t *)&DT1;
205
}
206

    
207
void helper_fors(void)
208
{
209
    *(uint32_t *)&FT0 |= *(uint32_t *)&FT1;
210
}
211

    
212
void helper_fxor(void)
213
{
214
    *(uint64_t *)&DT0 ^= *(uint64_t *)&DT1;
215
}
216

    
217
void helper_fxors(void)
218
{
219
    *(uint32_t *)&FT0 ^= *(uint32_t *)&FT1;
220
}
221

    
222
void helper_fand(void)
223
{
224
    *(uint64_t *)&DT0 &= *(uint64_t *)&DT1;
225
}
226

    
227
void helper_fands(void)
228
{
229
    *(uint32_t *)&FT0 &= *(uint32_t *)&FT1;
230
}
231

    
232
void helper_fornot(void)
233
{
234
    *(uint64_t *)&DT0 = *(uint64_t *)&DT0 | ~*(uint64_t *)&DT1;
235
}
236

    
237
void helper_fornots(void)
238
{
239
    *(uint32_t *)&FT0 = *(uint32_t *)&FT0 | ~*(uint32_t *)&FT1;
240
}
241

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

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

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

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

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

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

    
272
#ifdef WORDS_BIGENDIAN
273
#define VIS_B64(n) b[7 - (n)]
274
#define VIS_W64(n) w[3 - (n)]
275
#define VIS_SW64(n) sw[3 - (n)]
276
#define VIS_L64(n) l[1 - (n)]
277
#define VIS_B32(n) b[3 - (n)]
278
#define VIS_W32(n) w[1 - (n)]
279
#else
280
#define VIS_B64(n) b[n]
281
#define VIS_W64(n) w[n]
282
#define VIS_SW64(n) sw[n]
283
#define VIS_L64(n) l[n]
284
#define VIS_B32(n) b[n]
285
#define VIS_W32(n) w[n]
286
#endif
287

    
288
typedef union {
289
    uint8_t b[8];
290
    uint16_t w[4];
291
    int16_t sw[4];
292
    uint32_t l[2];
293
    float64 d;
294
} vis64;
295

    
296
typedef union {
297
    uint8_t b[4];
298
    uint16_t w[2];
299
    uint32_t l;
300
    float32 f;
301
} vis32;
302

    
303
void helper_fpmerge(void)
304
{
305
    vis64 s, d;
306

    
307
    s.d = DT0;
308
    d.d = DT1;
309

    
310
    // Reverse calculation order to handle overlap
311
    d.VIS_B64(7) = s.VIS_B64(3);
312
    d.VIS_B64(6) = d.VIS_B64(3);
313
    d.VIS_B64(5) = s.VIS_B64(2);
314
    d.VIS_B64(4) = d.VIS_B64(2);
315
    d.VIS_B64(3) = s.VIS_B64(1);
316
    d.VIS_B64(2) = d.VIS_B64(1);
317
    d.VIS_B64(1) = s.VIS_B64(0);
318
    //d.VIS_B64(0) = d.VIS_B64(0);
319

    
320
    DT0 = d.d;
321
}
322

    
323
void helper_fmul8x16(void)
324
{
325
    vis64 s, d;
326
    uint32_t tmp;
327

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

    
331
#define PMUL(r)                                                 \
332
    tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
333
    if ((tmp & 0xff) > 0x7f)                                    \
334
        tmp += 0x100;                                           \
335
    d.VIS_W64(r) = tmp >> 8;
336

    
337
    PMUL(0);
338
    PMUL(1);
339
    PMUL(2);
340
    PMUL(3);
341
#undef PMUL
342

    
343
    DT0 = d.d;
344
}
345

    
346
void helper_fmul8x16al(void)
347
{
348
    vis64 s, d;
349
    uint32_t tmp;
350

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

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

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

    
366
    DT0 = d.d;
367
}
368

    
369
void helper_fmul8x16au(void)
370
{
371
    vis64 s, d;
372
    uint32_t tmp;
373

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

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

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

    
389
    DT0 = d.d;
390
}
391

    
392
void helper_fmul8sux16(void)
393
{
394
    vis64 s, d;
395
    uint32_t tmp;
396

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

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

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

    
412
    DT0 = d.d;
413
}
414

    
415
void helper_fmul8ulx16(void)
416
{
417
    vis64 s, d;
418
    uint32_t tmp;
419

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

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

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

    
435
    DT0 = d.d;
436
}
437

    
438
void helper_fmuld8sux16(void)
439
{
440
    vis64 s, d;
441
    uint32_t tmp;
442

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

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

    
452
    // Reverse calculation order to handle overlap
453
    PMUL(1);
454
    PMUL(0);
455
#undef PMUL
456

    
457
    DT0 = d.d;
458
}
459

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

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

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

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

    
479
    DT0 = d.d;
480
}
481

    
482
void helper_fexpand(void)
483
{
484
    vis32 s;
485
    vis64 d;
486

    
487
    s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
488
    d.d = DT1;
489
    d.VIS_L64(0) = s.VIS_W32(0) << 4;
490
    d.VIS_L64(1) = s.VIS_W32(1) << 4;
491
    d.VIS_L64(2) = s.VIS_W32(2) << 4;
492
    d.VIS_L64(3) = s.VIS_W32(3) << 4;
493

    
494
    DT0 = d.d;
495
}
496

    
497
#define VIS_HELPER(name, F)                             \
498
    void name##16(void)                                 \
499
    {                                                   \
500
        vis64 s, d;                                     \
501
                                                        \
502
        s.d = DT0;                                      \
503
        d.d = DT1;                                      \
504
                                                        \
505
        d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
506
        d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
507
        d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
508
        d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
509
                                                        \
510
        DT0 = d.d;                                      \
511
    }                                                   \
512
                                                        \
513
    void name##16s(void)                                \
514
    {                                                   \
515
        vis32 s, d;                                     \
516
                                                        \
517
        s.f = FT0;                                      \
518
        d.f = FT1;                                      \
519
                                                        \
520
        d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
521
        d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
522
                                                        \
523
        FT0 = d.f;                                      \
524
    }                                                   \
525
                                                        \
526
    void name##32(void)                                 \
527
    {                                                   \
528
        vis64 s, d;                                     \
529
                                                        \
530
        s.d = DT0;                                      \
531
        d.d = DT1;                                      \
532
                                                        \
533
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
534
        d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
535
                                                        \
536
        DT0 = d.d;                                      \
537
    }                                                   \
538
                                                        \
539
    void name##32s(void)                                \
540
    {                                                   \
541
        vis32 s, d;                                     \
542
                                                        \
543
        s.f = FT0;                                      \
544
        d.f = FT1;                                      \
545
                                                        \
546
        d.l = F(d.l, s.l);                              \
547
                                                        \
548
        FT0 = d.f;                                      \
549
    }
550

    
551
#define FADD(a, b) ((a) + (b))
552
#define FSUB(a, b) ((a) - (b))
553
VIS_HELPER(helper_fpadd, FADD)
554
VIS_HELPER(helper_fpsub, FSUB)
555

    
556
#define VIS_CMPHELPER(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))? 1: 0;       \
565
        d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
566
        d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
567
        d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
568
                                                                  \
569
        DT0 = d.d;                                                \
570
    }                                                             \
571
                                                                  \
572
    void name##32(void)                                           \
573
    {                                                             \
574
        vis64 s, d;                                               \
575
                                                                  \
576
        s.d = DT0;                                                \
577
        d.d = DT1;                                                \
578
                                                                  \
579
        d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
580
        d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
581
                                                                  \
582
        DT0 = d.d;                                                \
583
    }
584

    
585
#define FCMPGT(a, b) ((a) > (b))
586
#define FCMPEQ(a, b) ((a) == (b))
587
#define FCMPLE(a, b) ((a) <= (b))
588
#define FCMPNE(a, b) ((a) != (b))
589

    
590
VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
591
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
592
VIS_CMPHELPER(helper_fcmple, FCMPLE)
593
VIS_CMPHELPER(helper_fcmpne, FCMPNE)
594
#endif
595

    
596
void helper_check_ieee_exceptions(void)
597
{
598
    target_ulong status;
599

    
600
    status = get_float_exception_flags(&env->fp_status);
601
    if (status) {
602
        /* Copy IEEE 754 flags into FSR */
603
        if (status & float_flag_invalid)
604
            env->fsr |= FSR_NVC;
605
        if (status & float_flag_overflow)
606
            env->fsr |= FSR_OFC;
607
        if (status & float_flag_underflow)
608
            env->fsr |= FSR_UFC;
609
        if (status & float_flag_divbyzero)
610
            env->fsr |= FSR_DZC;
611
        if (status & float_flag_inexact)
612
            env->fsr |= FSR_NXC;
613

    
614
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
615
            /* Unmasked exception, generate a trap */
616
            env->fsr |= FSR_FTT_IEEE_EXCP;
617
            raise_exception(TT_FP_EXCP);
618
        } else {
619
            /* Accumulate exceptions */
620
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
621
        }
622
    }
623
}
624

    
625
void helper_clear_float_exceptions(void)
626
{
627
    set_float_exception_flags(0, &env->fp_status);
628
}
629

    
630
void helper_fabss(void)
631
{
632
    FT0 = float32_abs(FT1);
633
}
634

    
635
#ifdef TARGET_SPARC64
636
void helper_fabsd(void)
637
{
638
    DT0 = float64_abs(DT1);
639
}
640
#endif
641

    
642
void helper_fsqrts(void)
643
{
644
    FT0 = float32_sqrt(FT1, &env->fp_status);
645
}
646

    
647
void helper_fsqrtd(void)
648
{
649
    DT0 = float64_sqrt(DT1, &env->fp_status);
650
}
651

    
652
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
653
    void glue(helper_, name) (void)                                     \
654
    {                                                                   \
655
        target_ulong new_fsr;                                           \
656
                                                                        \
657
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
658
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
659
        case float_relation_unordered:                                  \
660
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
661
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
662
                env->fsr |= new_fsr;                                    \
663
                env->fsr |= FSR_NVC;                                    \
664
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
665
                raise_exception(TT_FP_EXCP);                            \
666
            } else {                                                    \
667
                env->fsr |= FSR_NVA;                                    \
668
            }                                                           \
669
            break;                                                      \
670
        case float_relation_less:                                       \
671
            new_fsr = FSR_FCC0 << FS;                                   \
672
            break;                                                      \
673
        case float_relation_greater:                                    \
674
            new_fsr = FSR_FCC1 << FS;                                   \
675
            break;                                                      \
676
        default:                                                        \
677
            new_fsr = 0;                                                \
678
            break;                                                      \
679
        }                                                               \
680
        env->fsr |= new_fsr;                                            \
681
    }
682

    
683
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
684
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
685

    
686
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
687
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
688

    
689
#ifdef TARGET_SPARC64
690
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
691
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
692

    
693
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
694
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
695

    
696
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
697
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
698

    
699
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
700
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
701

    
702
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
703
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
704

    
705
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
706
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
707
#endif
708

    
709
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
710
static void dump_mxcc(CPUState *env)
711
{
712
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
713
        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
714
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
715
           "          %016llx %016llx %016llx %016llx\n",
716
        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
717
        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
718
}
719
#endif
720

    
721
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
722
    && defined(DEBUG_ASI)
723
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
724
                     uint64_t r1)
725
{
726
    switch (size)
727
    {
728
    case 1:
729
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
730
                    addr, asi, r1 & 0xff);
731
        break;
732
    case 2:
733
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
734
                    addr, asi, r1 & 0xffff);
735
        break;
736
    case 4:
737
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
738
                    addr, asi, r1 & 0xffffffff);
739
        break;
740
    case 8:
741
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
742
                    addr, asi, r1);
743
        break;
744
    }
745
}
746
#endif
747

    
748
#ifndef TARGET_SPARC64
749
#ifndef CONFIG_USER_ONLY
750
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
751
{
752
    uint64_t ret = 0;
753
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
754
    uint32_t last_addr = addr;
755
#endif
756

    
757
    switch (asi) {
758
    case 2: /* SuperSparc MXCC registers */
759
        switch (addr) {
760
        case 0x01c00a00: /* MXCC control register */
761
            if (size == 8)
762
                ret = env->mxccregs[3];
763
            else
764
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
765
            break;
766
        case 0x01c00a04: /* MXCC control register */
767
            if (size == 4)
768
                ret = env->mxccregs[3];
769
            else
770
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
771
            break;
772
        case 0x01c00c00: /* Module reset register */
773
            if (size == 8) {
774
                ret = env->mxccregs[5];
775
                // should we do something here?
776
            } else
777
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
778
            break;
779
        case 0x01c00f00: /* MBus port address register */
780
            if (size == 8)
781
                ret = env->mxccregs[7];
782
            else
783
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
784
            break;
785
        default:
786
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
787
            break;
788
        }
789
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
790
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
791
#ifdef DEBUG_MXCC
792
        dump_mxcc(env);
793
#endif
794
        break;
795
    case 3: /* MMU probe */
796
        {
797
            int mmulev;
798

    
799
            mmulev = (addr >> 8) & 15;
800
            if (mmulev > 4)
801
                ret = 0;
802
            else
803
                ret = mmu_probe(env, addr, mmulev);
804
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
805
                        addr, mmulev, ret);
806
        }
807
        break;
808
    case 4: /* read MMU regs */
809
        {
810
            int reg = (addr >> 8) & 0x1f;
811

    
812
            ret = env->mmuregs[reg];
813
            if (reg == 3) /* Fault status cleared on read */
814
                env->mmuregs[3] = 0;
815
            else if (reg == 0x13) /* Fault status read */
816
                ret = env->mmuregs[3];
817
            else if (reg == 0x14) /* Fault address read */
818
                ret = env->mmuregs[4];
819
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
820
        }
821
        break;
822
    case 5: // Turbosparc ITLB Diagnostic
823
    case 6: // Turbosparc DTLB Diagnostic
824
    case 7: // Turbosparc IOTLB Diagnostic
825
        break;
826
    case 9: /* Supervisor code access */
827
        switch(size) {
828
        case 1:
829
            ret = ldub_code(addr);
830
            break;
831
        case 2:
832
            ret = lduw_code(addr & ~1);
833
            break;
834
        default:
835
        case 4:
836
            ret = ldl_code(addr & ~3);
837
            break;
838
        case 8:
839
            ret = ldq_code(addr & ~7);
840
            break;
841
        }
842
        break;
843
    case 0xa: /* User data access */
844
        switch(size) {
845
        case 1:
846
            ret = ldub_user(addr);
847
            break;
848
        case 2:
849
            ret = lduw_user(addr & ~1);
850
            break;
851
        default:
852
        case 4:
853
            ret = ldl_user(addr & ~3);
854
            break;
855
        case 8:
856
            ret = ldq_user(addr & ~7);
857
            break;
858
        }
859
        break;
860
    case 0xb: /* Supervisor data access */
861
        switch(size) {
862
        case 1:
863
            ret = ldub_kernel(addr);
864
            break;
865
        case 2:
866
            ret = lduw_kernel(addr & ~1);
867
            break;
868
        default:
869
        case 4:
870
            ret = ldl_kernel(addr & ~3);
871
            break;
872
        case 8:
873
            ret = ldq_kernel(addr & ~7);
874
            break;
875
        }
876
        break;
877
    case 0xc: /* I-cache tag */
878
    case 0xd: /* I-cache data */
879
    case 0xe: /* D-cache tag */
880
    case 0xf: /* D-cache data */
881
        break;
882
    case 0x20: /* MMU passthrough */
883
        switch(size) {
884
        case 1:
885
            ret = ldub_phys(addr);
886
            break;
887
        case 2:
888
            ret = lduw_phys(addr & ~1);
889
            break;
890
        default:
891
        case 4:
892
            ret = ldl_phys(addr & ~3);
893
            break;
894
        case 8:
895
            ret = ldq_phys(addr & ~7);
896
            break;
897
        }
898
        break;
899
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
900
        switch(size) {
901
        case 1:
902
            ret = ldub_phys((target_phys_addr_t)addr
903
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
904
            break;
905
        case 2:
906
            ret = lduw_phys((target_phys_addr_t)(addr & ~1)
907
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
908
            break;
909
        default:
910
        case 4:
911
            ret = ldl_phys((target_phys_addr_t)(addr & ~3)
912
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
913
            break;
914
        case 8:
915
            ret = ldq_phys((target_phys_addr_t)(addr & ~7)
916
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
917
            break;
918
        }
919
        break;
920
    case 0x30: // Turbosparc secondary cache diagnostic
921
    case 0x31: // Turbosparc RAM snoop
922
    case 0x32: // Turbosparc page table descriptor diagnostic
923
    case 0x39: /* data cache diagnostic register */
924
        ret = 0;
925
        break;
926
    case 8: /* User code access, XXX */
927
    default:
928
        do_unassigned_access(addr, 0, 0, asi);
929
        ret = 0;
930
        break;
931
    }
932
    if (sign) {
933
        switch(size) {
934
        case 1:
935
            ret = (int8_t) ret;
936
            break;
937
        case 2:
938
            ret = (int16_t) ret;
939
            break;
940
        case 4:
941
            ret = (int32_t) ret;
942
            break;
943
        default:
944
            break;
945
        }
946
    }
947
#ifdef DEBUG_ASI
948
    dump_asi("read ", last_addr, asi, size, ret);
949
#endif
950
    return ret;
951
}
952

    
953
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
954
{
955
    switch(asi) {
956
    case 2: /* SuperSparc MXCC registers */
957
        switch (addr) {
958
        case 0x01c00000: /* MXCC stream data register 0 */
959
            if (size == 8)
960
                env->mxccdata[0] = val;
961
            else
962
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
963
            break;
964
        case 0x01c00008: /* MXCC stream data register 1 */
965
            if (size == 8)
966
                env->mxccdata[1] = val;
967
            else
968
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
969
            break;
970
        case 0x01c00010: /* MXCC stream data register 2 */
971
            if (size == 8)
972
                env->mxccdata[2] = val;
973
            else
974
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
975
            break;
976
        case 0x01c00018: /* MXCC stream data register 3 */
977
            if (size == 8)
978
                env->mxccdata[3] = val;
979
            else
980
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
981
            break;
982
        case 0x01c00100: /* MXCC stream source */
983
            if (size == 8)
984
                env->mxccregs[0] = val;
985
            else
986
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
987
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
988
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
989
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
990
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
991
            break;
992
        case 0x01c00200: /* MXCC stream destination */
993
            if (size == 8)
994
                env->mxccregs[1] = val;
995
            else
996
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
997
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
998
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
999
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
1000
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
1001
            break;
1002
        case 0x01c00a00: /* MXCC control register */
1003
            if (size == 8)
1004
                env->mxccregs[3] = val;
1005
            else
1006
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1007
            break;
1008
        case 0x01c00a04: /* MXCC control register */
1009
            if (size == 4)
1010
                env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val;
1011
            else
1012
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1013
            break;
1014
        case 0x01c00e00: /* MXCC error register  */
1015
            // writing a 1 bit clears the error
1016
            if (size == 8)
1017
                env->mxccregs[6] &= ~val;
1018
            else
1019
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1020
            break;
1021
        case 0x01c00f00: /* MBus port address register */
1022
            if (size == 8)
1023
                env->mxccregs[7] = val;
1024
            else
1025
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
1026
            break;
1027
        default:
1028
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
1029
            break;
1030
        }
1031
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);
1032
#ifdef DEBUG_MXCC
1033
        dump_mxcc(env);
1034
#endif
1035
        break;
1036
    case 3: /* MMU flush */
1037
        {
1038
            int mmulev;
1039

    
1040
            mmulev = (addr >> 8) & 15;
1041
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
1042
            switch (mmulev) {
1043
            case 0: // flush page
1044
                tlb_flush_page(env, addr & 0xfffff000);
1045
                break;
1046
            case 1: // flush segment (256k)
1047
            case 2: // flush region (16M)
1048
            case 3: // flush context (4G)
1049
            case 4: // flush entire
1050
                tlb_flush(env, 1);
1051
                break;
1052
            default:
1053
                break;
1054
            }
1055
#ifdef DEBUG_MMU
1056
            dump_mmu(env);
1057
#endif
1058
        }
1059
        break;
1060
    case 4: /* write MMU regs */
1061
        {
1062
            int reg = (addr >> 8) & 0x1f;
1063
            uint32_t oldreg;
1064

    
1065
            oldreg = env->mmuregs[reg];
1066
            switch(reg) {
1067
            case 0: // Control Register
1068
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1069
                                    (val & 0x00ffffff);
1070
                // Mappings generated during no-fault mode or MMU
1071
                // disabled mode are invalid in normal mode
1072
                if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
1073
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
1074
                    tlb_flush(env, 1);
1075
                break;
1076
            case 1: // Context Table Pointer Register
1077
                env->mmuregs[reg] = val & env->mmu_ctpr_mask;
1078
                break;
1079
            case 2: // Context Register
1080
                env->mmuregs[reg] = val & env->mmu_cxr_mask;
1081
                if (oldreg != env->mmuregs[reg]) {
1082
                    /* we flush when the MMU context changes because
1083
                       QEMU has no MMU context support */
1084
                    tlb_flush(env, 1);
1085
                }
1086
                break;
1087
            case 3: // Synchronous Fault Status Register with Clear
1088
            case 4: // Synchronous Fault Address Register
1089
                break;
1090
            case 0x10: // TLB Replacement Control Register
1091
                env->mmuregs[reg] = val & env->mmu_trcr_mask;
1092
                break;
1093
            case 0x13: // Synchronous Fault Status Register with Read and Clear
1094
                env->mmuregs[3] = val & env->mmu_sfsr_mask;
1095
                break;
1096
            case 0x14: // Synchronous Fault Address Register
1097
                env->mmuregs[4] = val;
1098
                break;
1099
            default:
1100
                env->mmuregs[reg] = val;
1101
                break;
1102
            }
1103
            if (oldreg != env->mmuregs[reg]) {
1104
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
1105
            }
1106
#ifdef DEBUG_MMU
1107
            dump_mmu(env);
1108
#endif
1109
        }
1110
        break;
1111
    case 5: // Turbosparc ITLB Diagnostic
1112
    case 6: // Turbosparc DTLB Diagnostic
1113
    case 7: // Turbosparc IOTLB Diagnostic
1114
        break;
1115
    case 0xa: /* User data access */
1116
        switch(size) {
1117
        case 1:
1118
            stb_user(addr, val);
1119
            break;
1120
        case 2:
1121
            stw_user(addr & ~1, val);
1122
            break;
1123
        default:
1124
        case 4:
1125
            stl_user(addr & ~3, val);
1126
            break;
1127
        case 8:
1128
            stq_user(addr & ~7, val);
1129
            break;
1130
        }
1131
        break;
1132
    case 0xb: /* Supervisor data access */
1133
        switch(size) {
1134
        case 1:
1135
            stb_kernel(addr, val);
1136
            break;
1137
        case 2:
1138
            stw_kernel(addr & ~1, val);
1139
            break;
1140
        default:
1141
        case 4:
1142
            stl_kernel(addr & ~3, val);
1143
            break;
1144
        case 8:
1145
            stq_kernel(addr & ~7, val);
1146
            break;
1147
        }
1148
        break;
1149
    case 0xc: /* I-cache tag */
1150
    case 0xd: /* I-cache data */
1151
    case 0xe: /* D-cache tag */
1152
    case 0xf: /* D-cache data */
1153
    case 0x10: /* I/D-cache flush page */
1154
    case 0x11: /* I/D-cache flush segment */
1155
    case 0x12: /* I/D-cache flush region */
1156
    case 0x13: /* I/D-cache flush context */
1157
    case 0x14: /* I/D-cache flush user */
1158
        break;
1159
    case 0x17: /* Block copy, sta access */
1160
        {
1161
            // val = src
1162
            // addr = dst
1163
            // copy 32 bytes
1164
            unsigned int i;
1165
            uint32_t src = val & ~3, dst = addr & ~3, temp;
1166

    
1167
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
1168
                temp = ldl_kernel(src);
1169
                stl_kernel(dst, temp);
1170
            }
1171
        }
1172
        break;
1173
    case 0x1f: /* Block fill, stda access */
1174
        {
1175
            // addr = dst
1176
            // fill 32 bytes with val
1177
            unsigned int i;
1178
            uint32_t dst = addr & 7;
1179

    
1180
            for (i = 0; i < 32; i += 8, dst += 8)
1181
                stq_kernel(dst, val);
1182
        }
1183
        break;
1184
    case 0x20: /* MMU passthrough */
1185
        {
1186
            switch(size) {
1187
            case 1:
1188
                stb_phys(addr, val);
1189
                break;
1190
            case 2:
1191
                stw_phys(addr & ~1, val);
1192
                break;
1193
            case 4:
1194
            default:
1195
                stl_phys(addr & ~3, val);
1196
                break;
1197
            case 8:
1198
                stq_phys(addr & ~7, val);
1199
                break;
1200
            }
1201
        }
1202
        break;
1203
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
1204
        {
1205
            switch(size) {
1206
            case 1:
1207
                stb_phys((target_phys_addr_t)addr
1208
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1209
                break;
1210
            case 2:
1211
                stw_phys((target_phys_addr_t)(addr & ~1)
1212
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1213
                break;
1214
            case 4:
1215
            default:
1216
                stl_phys((target_phys_addr_t)(addr & ~3)
1217
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1218
                break;
1219
            case 8:
1220
                stq_phys((target_phys_addr_t)(addr & ~7)
1221
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1222
                break;
1223
            }
1224
        }
1225
        break;
1226
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
1227
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
1228
               // Turbosparc snoop RAM
1229
    case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
1230
    case 0x36: /* I-cache flash clear */
1231
    case 0x37: /* D-cache flash clear */
1232
    case 0x38: /* breakpoint diagnostics */
1233
    case 0x4c: /* breakpoint action */
1234
        break;
1235
    case 8: /* User code access, XXX */
1236
    case 9: /* Supervisor code access, XXX */
1237
    default:
1238
        do_unassigned_access(addr, 1, 0, asi);
1239
        break;
1240
    }
1241
#ifdef DEBUG_ASI
1242
    dump_asi("write", addr, asi, size, val);
1243
#endif
1244
}
1245

    
1246
#endif /* CONFIG_USER_ONLY */
1247
#else /* TARGET_SPARC64 */
1248

    
1249
#ifdef CONFIG_USER_ONLY
1250
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1251
{
1252
    uint64_t ret = 0;
1253
#if defined(DEBUG_ASI)
1254
    target_ulong last_addr = addr;
1255
#endif
1256

    
1257
    if (asi < 0x80)
1258
        raise_exception(TT_PRIV_ACT);
1259

    
1260
    switch (asi) {
1261
    case 0x80: // Primary
1262
    case 0x82: // Primary no-fault
1263
    case 0x88: // Primary LE
1264
    case 0x8a: // Primary no-fault LE
1265
        {
1266
            switch(size) {
1267
            case 1:
1268
                ret = ldub_raw(addr);
1269
                break;
1270
            case 2:
1271
                ret = lduw_raw(addr & ~1);
1272
                break;
1273
            case 4:
1274
                ret = ldl_raw(addr & ~3);
1275
                break;
1276
            default:
1277
            case 8:
1278
                ret = ldq_raw(addr & ~7);
1279
                break;
1280
            }
1281
        }
1282
        break;
1283
    case 0x81: // Secondary
1284
    case 0x83: // Secondary no-fault
1285
    case 0x89: // Secondary LE
1286
    case 0x8b: // Secondary no-fault LE
1287
        // XXX
1288
        break;
1289
    default:
1290
        break;
1291
    }
1292

    
1293
    /* Convert from little endian */
1294
    switch (asi) {
1295
    case 0x88: // Primary LE
1296
    case 0x89: // Secondary LE
1297
    case 0x8a: // Primary no-fault LE
1298
    case 0x8b: // Secondary no-fault LE
1299
        switch(size) {
1300
        case 2:
1301
            ret = bswap16(ret);
1302
            break;
1303
        case 4:
1304
            ret = bswap32(ret);
1305
            break;
1306
        case 8:
1307
            ret = bswap64(ret);
1308
            break;
1309
        default:
1310
            break;
1311
        }
1312
    default:
1313
        break;
1314
    }
1315

    
1316
    /* Convert to signed number */
1317
    if (sign) {
1318
        switch(size) {
1319
        case 1:
1320
            ret = (int8_t) ret;
1321
            break;
1322
        case 2:
1323
            ret = (int16_t) ret;
1324
            break;
1325
        case 4:
1326
            ret = (int32_t) ret;
1327
            break;
1328
        default:
1329
            break;
1330
        }
1331
    }
1332
#ifdef DEBUG_ASI
1333
    dump_asi("read ", last_addr, asi, size, ret);
1334
#endif
1335
    return ret;
1336
}
1337

    
1338
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1339
{
1340
#ifdef DEBUG_ASI
1341
    dump_asi("write", addr, asi, size, val);
1342
#endif
1343
    if (asi < 0x80)
1344
        raise_exception(TT_PRIV_ACT);
1345

    
1346
    /* Convert to little endian */
1347
    switch (asi) {
1348
    case 0x88: // Primary LE
1349
    case 0x89: // Secondary LE
1350
        switch(size) {
1351
        case 2:
1352
            addr = bswap16(addr);
1353
            break;
1354
        case 4:
1355
            addr = bswap32(addr);
1356
            break;
1357
        case 8:
1358
            addr = bswap64(addr);
1359
            break;
1360
        default:
1361
            break;
1362
        }
1363
    default:
1364
        break;
1365
    }
1366

    
1367
    switch(asi) {
1368
    case 0x80: // Primary
1369
    case 0x88: // Primary LE
1370
        {
1371
            switch(size) {
1372
            case 1:
1373
                stb_raw(addr, val);
1374
                break;
1375
            case 2:
1376
                stw_raw(addr & ~1, val);
1377
                break;
1378
            case 4:
1379
                stl_raw(addr & ~3, val);
1380
                break;
1381
            case 8:
1382
            default:
1383
                stq_raw(addr & ~7, val);
1384
                break;
1385
            }
1386
        }
1387
        break;
1388
    case 0x81: // Secondary
1389
    case 0x89: // Secondary LE
1390
        // XXX
1391
        return;
1392

    
1393
    case 0x82: // Primary no-fault, RO
1394
    case 0x83: // Secondary no-fault, RO
1395
    case 0x8a: // Primary no-fault LE, RO
1396
    case 0x8b: // Secondary no-fault LE, RO
1397
    default:
1398
        do_unassigned_access(addr, 1, 0, 1);
1399
        return;
1400
    }
1401
}
1402

    
1403
#else /* CONFIG_USER_ONLY */
1404

    
1405
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1406
{
1407
    uint64_t ret = 0;
1408
#if defined(DEBUG_ASI)
1409
    target_ulong last_addr = addr;
1410
#endif
1411

    
1412
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1413
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1414
        raise_exception(TT_PRIV_ACT);
1415

    
1416
    switch (asi) {
1417
    case 0x10: // As if user primary
1418
    case 0x18: // As if user primary LE
1419
    case 0x80: // Primary
1420
    case 0x82: // Primary no-fault
1421
    case 0x88: // Primary LE
1422
    case 0x8a: // Primary no-fault LE
1423
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1424
            if (env->hpstate & HS_PRIV) {
1425
                switch(size) {
1426
                case 1:
1427
                    ret = ldub_hypv(addr);
1428
                    break;
1429
                case 2:
1430
                    ret = lduw_hypv(addr & ~1);
1431
                    break;
1432
                case 4:
1433
                    ret = ldl_hypv(addr & ~3);
1434
                    break;
1435
                default:
1436
                case 8:
1437
                    ret = ldq_hypv(addr & ~7);
1438
                    break;
1439
                }
1440
            } else {
1441
                switch(size) {
1442
                case 1:
1443
                    ret = ldub_kernel(addr);
1444
                    break;
1445
                case 2:
1446
                    ret = lduw_kernel(addr & ~1);
1447
                    break;
1448
                case 4:
1449
                    ret = ldl_kernel(addr & ~3);
1450
                    break;
1451
                default:
1452
                case 8:
1453
                    ret = ldq_kernel(addr & ~7);
1454
                    break;
1455
                }
1456
            }
1457
        } else {
1458
            switch(size) {
1459
            case 1:
1460
                ret = ldub_user(addr);
1461
                break;
1462
            case 2:
1463
                ret = lduw_user(addr & ~1);
1464
                break;
1465
            case 4:
1466
                ret = ldl_user(addr & ~3);
1467
                break;
1468
            default:
1469
            case 8:
1470
                ret = ldq_user(addr & ~7);
1471
                break;
1472
            }
1473
        }
1474
        break;
1475
    case 0x14: // Bypass
1476
    case 0x15: // Bypass, non-cacheable
1477
    case 0x1c: // Bypass LE
1478
    case 0x1d: // Bypass, non-cacheable LE
1479
        {
1480
            switch(size) {
1481
            case 1:
1482
                ret = ldub_phys(addr);
1483
                break;
1484
            case 2:
1485
                ret = lduw_phys(addr & ~1);
1486
                break;
1487
            case 4:
1488
                ret = ldl_phys(addr & ~3);
1489
                break;
1490
            default:
1491
            case 8:
1492
                ret = ldq_phys(addr & ~7);
1493
                break;
1494
            }
1495
            break;
1496
        }
1497
    case 0x04: // Nucleus
1498
    case 0x0c: // Nucleus Little Endian (LE)
1499
    case 0x11: // As if user secondary
1500
    case 0x19: // As if user secondary LE
1501
    case 0x24: // Nucleus quad LDD 128 bit atomic
1502
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1503
    case 0x4a: // UPA config
1504
    case 0x81: // Secondary
1505
    case 0x83: // Secondary no-fault
1506
    case 0x89: // Secondary LE
1507
    case 0x8b: // Secondary no-fault LE
1508
        // XXX
1509
        break;
1510
    case 0x45: // LSU
1511
        ret = env->lsu;
1512
        break;
1513
    case 0x50: // I-MMU regs
1514
        {
1515
            int reg = (addr >> 3) & 0xf;
1516

    
1517
            ret = env->immuregs[reg];
1518
            break;
1519
        }
1520
    case 0x51: // I-MMU 8k TSB pointer
1521
    case 0x52: // I-MMU 64k TSB pointer
1522
    case 0x55: // I-MMU data access
1523
        // XXX
1524
        break;
1525
    case 0x56: // I-MMU tag read
1526
        {
1527
            unsigned int i;
1528

    
1529
            for (i = 0; i < 64; i++) {
1530
                // Valid, ctx match, vaddr match
1531
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1532
                    env->itlb_tag[i] == addr) {
1533
                    ret = env->itlb_tag[i];
1534
                    break;
1535
                }
1536
            }
1537
            break;
1538
        }
1539
    case 0x58: // D-MMU regs
1540
        {
1541
            int reg = (addr >> 3) & 0xf;
1542

    
1543
            ret = env->dmmuregs[reg];
1544
            break;
1545
        }
1546
    case 0x5e: // D-MMU tag read
1547
        {
1548
            unsigned int i;
1549

    
1550
            for (i = 0; i < 64; i++) {
1551
                // Valid, ctx match, vaddr match
1552
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1553
                    env->dtlb_tag[i] == addr) {
1554
                    ret = env->dtlb_tag[i];
1555
                    break;
1556
                }
1557
            }
1558
            break;
1559
        }
1560
    case 0x59: // D-MMU 8k TSB pointer
1561
    case 0x5a: // D-MMU 64k TSB pointer
1562
    case 0x5b: // D-MMU data pointer
1563
    case 0x5d: // D-MMU data access
1564
    case 0x48: // Interrupt dispatch, RO
1565
    case 0x49: // Interrupt data receive
1566
    case 0x7f: // Incoming interrupt vector, RO
1567
        // XXX
1568
        break;
1569
    case 0x54: // I-MMU data in, WO
1570
    case 0x57: // I-MMU demap, WO
1571
    case 0x5c: // D-MMU data in, WO
1572
    case 0x5f: // D-MMU demap, WO
1573
    case 0x77: // Interrupt vector, WO
1574
    default:
1575
        do_unassigned_access(addr, 0, 0, 1);
1576
        ret = 0;
1577
        break;
1578
    }
1579

    
1580
    /* Convert from little endian */
1581
    switch (asi) {
1582
    case 0x0c: // Nucleus Little Endian (LE)
1583
    case 0x18: // As if user primary LE
1584
    case 0x19: // As if user secondary LE
1585
    case 0x1c: // Bypass LE
1586
    case 0x1d: // Bypass, non-cacheable LE
1587
    case 0x88: // Primary LE
1588
    case 0x89: // Secondary LE
1589
    case 0x8a: // Primary no-fault LE
1590
    case 0x8b: // Secondary no-fault LE
1591
        switch(size) {
1592
        case 2:
1593
            ret = bswap16(ret);
1594
            break;
1595
        case 4:
1596
            ret = bswap32(ret);
1597
            break;
1598
        case 8:
1599
            ret = bswap64(ret);
1600
            break;
1601
        default:
1602
            break;
1603
        }
1604
    default:
1605
        break;
1606
    }
1607

    
1608
    /* Convert to signed number */
1609
    if (sign) {
1610
        switch(size) {
1611
        case 1:
1612
            ret = (int8_t) ret;
1613
            break;
1614
        case 2:
1615
            ret = (int16_t) ret;
1616
            break;
1617
        case 4:
1618
            ret = (int32_t) ret;
1619
            break;
1620
        default:
1621
            break;
1622
        }
1623
    }
1624
#ifdef DEBUG_ASI
1625
    dump_asi("read ", last_addr, asi, size, ret);
1626
#endif
1627
    return ret;
1628
}
1629

    
1630
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1631
{
1632
#ifdef DEBUG_ASI
1633
    dump_asi("write", addr, asi, size, val);
1634
#endif
1635
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1636
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1637
        raise_exception(TT_PRIV_ACT);
1638

    
1639
    /* Convert to little endian */
1640
    switch (asi) {
1641
    case 0x0c: // Nucleus Little Endian (LE)
1642
    case 0x18: // As if user primary LE
1643
    case 0x19: // As if user secondary LE
1644
    case 0x1c: // Bypass LE
1645
    case 0x1d: // Bypass, non-cacheable LE
1646
    case 0x88: // Primary LE
1647
    case 0x89: // Secondary LE
1648
        switch(size) {
1649
        case 2:
1650
            addr = bswap16(addr);
1651
            break;
1652
        case 4:
1653
            addr = bswap32(addr);
1654
            break;
1655
        case 8:
1656
            addr = bswap64(addr);
1657
            break;
1658
        default:
1659
            break;
1660
        }
1661
    default:
1662
        break;
1663
    }
1664

    
1665
    switch(asi) {
1666
    case 0x10: // As if user primary
1667
    case 0x18: // As if user primary LE
1668
    case 0x80: // Primary
1669
    case 0x88: // Primary LE
1670
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1671
            if (env->hpstate & HS_PRIV) {
1672
                switch(size) {
1673
                case 1:
1674
                    stb_hypv(addr, val);
1675
                    break;
1676
                case 2:
1677
                    stw_hypv(addr & ~1, val);
1678
                    break;
1679
                case 4:
1680
                    stl_hypv(addr & ~3, val);
1681
                    break;
1682
                case 8:
1683
                default:
1684
                    stq_hypv(addr & ~7, val);
1685
                    break;
1686
                }
1687
            } else {
1688
                switch(size) {
1689
                case 1:
1690
                    stb_kernel(addr, val);
1691
                    break;
1692
                case 2:
1693
                    stw_kernel(addr & ~1, val);
1694
                    break;
1695
                case 4:
1696
                    stl_kernel(addr & ~3, val);
1697
                    break;
1698
                case 8:
1699
                default:
1700
                    stq_kernel(addr & ~7, val);
1701
                    break;
1702
                }
1703
            }
1704
        } else {
1705
            switch(size) {
1706
            case 1:
1707
                stb_user(addr, val);
1708
                break;
1709
            case 2:
1710
                stw_user(addr & ~1, val);
1711
                break;
1712
            case 4:
1713
                stl_user(addr & ~3, val);
1714
                break;
1715
            case 8:
1716
            default:
1717
                stq_user(addr & ~7, val);
1718
                break;
1719
            }
1720
        }
1721
        break;
1722
    case 0x14: // Bypass
1723
    case 0x15: // Bypass, non-cacheable
1724
    case 0x1c: // Bypass LE
1725
    case 0x1d: // Bypass, non-cacheable LE
1726
        {
1727
            switch(size) {
1728
            case 1:
1729
                stb_phys(addr, val);
1730
                break;
1731
            case 2:
1732
                stw_phys(addr & ~1, val);
1733
                break;
1734
            case 4:
1735
                stl_phys(addr & ~3, val);
1736
                break;
1737
            case 8:
1738
            default:
1739
                stq_phys(addr & ~7, val);
1740
                break;
1741
            }
1742
        }
1743
        return;
1744
    case 0x04: // Nucleus
1745
    case 0x0c: // Nucleus Little Endian (LE)
1746
    case 0x11: // As if user secondary
1747
    case 0x19: // As if user secondary LE
1748
    case 0x24: // Nucleus quad LDD 128 bit atomic
1749
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1750
    case 0x4a: // UPA config
1751
    case 0x81: // Secondary
1752
    case 0x89: // Secondary LE
1753
        // XXX
1754
        return;
1755
    case 0x45: // LSU
1756
        {
1757
            uint64_t oldreg;
1758

    
1759
            oldreg = env->lsu;
1760
            env->lsu = val & (DMMU_E | IMMU_E);
1761
            // Mappings generated during D/I MMU disabled mode are
1762
            // invalid in normal mode
1763
            if (oldreg != env->lsu) {
1764
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1765
#ifdef DEBUG_MMU
1766
                dump_mmu(env);
1767
#endif
1768
                tlb_flush(env, 1);
1769
            }
1770
            return;
1771
        }
1772
    case 0x50: // I-MMU regs
1773
        {
1774
            int reg = (addr >> 3) & 0xf;
1775
            uint64_t oldreg;
1776

    
1777
            oldreg = env->immuregs[reg];
1778
            switch(reg) {
1779
            case 0: // RO
1780
            case 4:
1781
                return;
1782
            case 1: // Not in I-MMU
1783
            case 2:
1784
            case 7:
1785
            case 8:
1786
                return;
1787
            case 3: // SFSR
1788
                if ((val & 1) == 0)
1789
                    val = 0; // Clear SFSR
1790
                break;
1791
            case 5: // TSB access
1792
            case 6: // Tag access
1793
            default:
1794
                break;
1795
            }
1796
            env->immuregs[reg] = val;
1797
            if (oldreg != env->immuregs[reg]) {
1798
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1799
            }
1800
#ifdef DEBUG_MMU
1801
            dump_mmu(env);
1802
#endif
1803
            return;
1804
        }
1805
    case 0x54: // I-MMU data in
1806
        {
1807
            unsigned int i;
1808

    
1809
            // Try finding an invalid entry
1810
            for (i = 0; i < 64; i++) {
1811
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1812
                    env->itlb_tag[i] = env->immuregs[6];
1813
                    env->itlb_tte[i] = val;
1814
                    return;
1815
                }
1816
            }
1817
            // Try finding an unlocked entry
1818
            for (i = 0; i < 64; i++) {
1819
                if ((env->itlb_tte[i] & 0x40) == 0) {
1820
                    env->itlb_tag[i] = env->immuregs[6];
1821
                    env->itlb_tte[i] = val;
1822
                    return;
1823
                }
1824
            }
1825
            // error state?
1826
            return;
1827
        }
1828
    case 0x55: // I-MMU data access
1829
        {
1830
            unsigned int i = (addr >> 3) & 0x3f;
1831

    
1832
            env->itlb_tag[i] = env->immuregs[6];
1833
            env->itlb_tte[i] = val;
1834
            return;
1835
        }
1836
    case 0x57: // I-MMU demap
1837
        // XXX
1838
        return;
1839
    case 0x58: // D-MMU regs
1840
        {
1841
            int reg = (addr >> 3) & 0xf;
1842
            uint64_t oldreg;
1843

    
1844
            oldreg = env->dmmuregs[reg];
1845
            switch(reg) {
1846
            case 0: // RO
1847
            case 4:
1848
                return;
1849
            case 3: // SFSR
1850
                if ((val & 1) == 0) {
1851
                    val = 0; // Clear SFSR, Fault address
1852
                    env->dmmuregs[4] = 0;
1853
                }
1854
                env->dmmuregs[reg] = val;
1855
                break;
1856
            case 1: // Primary context
1857
            case 2: // Secondary context
1858
            case 5: // TSB access
1859
            case 6: // Tag access
1860
            case 7: // Virtual Watchpoint
1861
            case 8: // Physical Watchpoint
1862
            default:
1863
                break;
1864
            }
1865
            env->dmmuregs[reg] = val;
1866
            if (oldreg != env->dmmuregs[reg]) {
1867
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1868
            }
1869
#ifdef DEBUG_MMU
1870
            dump_mmu(env);
1871
#endif
1872
            return;
1873
        }
1874
    case 0x5c: // D-MMU data in
1875
        {
1876
            unsigned int i;
1877

    
1878
            // Try finding an invalid entry
1879
            for (i = 0; i < 64; i++) {
1880
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1881
                    env->dtlb_tag[i] = env->dmmuregs[6];
1882
                    env->dtlb_tte[i] = val;
1883
                    return;
1884
                }
1885
            }
1886
            // Try finding an unlocked entry
1887
            for (i = 0; i < 64; i++) {
1888
                if ((env->dtlb_tte[i] & 0x40) == 0) {
1889
                    env->dtlb_tag[i] = env->dmmuregs[6];
1890
                    env->dtlb_tte[i] = val;
1891
                    return;
1892
                }
1893
            }
1894
            // error state?
1895
            return;
1896
        }
1897
    case 0x5d: // D-MMU data access
1898
        {
1899
            unsigned int i = (addr >> 3) & 0x3f;
1900

    
1901
            env->dtlb_tag[i] = env->dmmuregs[6];
1902
            env->dtlb_tte[i] = val;
1903
            return;
1904
        }
1905
    case 0x5f: // D-MMU demap
1906
    case 0x49: // Interrupt data receive
1907
        // XXX
1908
        return;
1909
    case 0x51: // I-MMU 8k TSB pointer, RO
1910
    case 0x52: // I-MMU 64k TSB pointer, RO
1911
    case 0x56: // I-MMU tag read, RO
1912
    case 0x59: // D-MMU 8k TSB pointer, RO
1913
    case 0x5a: // D-MMU 64k TSB pointer, RO
1914
    case 0x5b: // D-MMU data pointer, RO
1915
    case 0x5e: // D-MMU tag read, RO
1916
    case 0x48: // Interrupt dispatch, RO
1917
    case 0x7f: // Incoming interrupt vector, RO
1918
    case 0x82: // Primary no-fault, RO
1919
    case 0x83: // Secondary no-fault, RO
1920
    case 0x8a: // Primary no-fault LE, RO
1921
    case 0x8b: // Secondary no-fault LE, RO
1922
    default:
1923
        do_unassigned_access(addr, 1, 0, 1);
1924
        return;
1925
    }
1926
}
1927
#endif /* CONFIG_USER_ONLY */
1928

    
1929
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
1930
{
1931
    unsigned int i;
1932
    target_ulong val;
1933

    
1934
    switch (asi) {
1935
    case 0xf0: // Block load primary
1936
    case 0xf1: // Block load secondary
1937
    case 0xf8: // Block load primary LE
1938
    case 0xf9: // Block load secondary LE
1939
        if (rd & 7) {
1940
            raise_exception(TT_ILL_INSN);
1941
            return;
1942
        }
1943
        if (addr & 0x3f) {
1944
            raise_exception(TT_UNALIGNED);
1945
            return;
1946
        }
1947
        for (i = 0; i < 16; i++) {
1948
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
1949
            addr += 4;
1950
        }
1951

    
1952
        return;
1953
    default:
1954
        break;
1955
    }
1956

    
1957
    val = helper_ld_asi(addr, asi, size, 0);
1958
    switch(size) {
1959
    default:
1960
    case 4:
1961
        *((uint32_t *)&FT0) = val;
1962
        break;
1963
    case 8:
1964
        *((int64_t *)&DT0) = val;
1965
        break;
1966
#if defined(CONFIG_USER_ONLY)
1967
    case 16:
1968
        // XXX
1969
        break;
1970
#endif
1971
    }
1972
}
1973

    
1974
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
1975
{
1976
    unsigned int i;
1977
    target_ulong val = 0;
1978

    
1979
    switch (asi) {
1980
    case 0xf0: // Block store primary
1981
    case 0xf1: // Block store secondary
1982
    case 0xf8: // Block store primary LE
1983
    case 0xf9: // Block store secondary LE
1984
        if (rd & 7) {
1985
            raise_exception(TT_ILL_INSN);
1986
            return;
1987
        }
1988
        if (addr & 0x3f) {
1989
            raise_exception(TT_UNALIGNED);
1990
            return;
1991
        }
1992
        for (i = 0; i < 16; i++) {
1993
            val = *(uint32_t *)&env->fpr[rd++];
1994
            helper_st_asi(addr, val, asi & 0x8f, 4);
1995
            addr += 4;
1996
        }
1997

    
1998
        return;
1999
    default:
2000
        break;
2001
    }
2002

    
2003
    switch(size) {
2004
    default:
2005
    case 4:
2006
        val = *((uint32_t *)&FT0);
2007
        break;
2008
    case 8:
2009
        val = *((int64_t *)&DT0);
2010
        break;
2011
#if defined(CONFIG_USER_ONLY)
2012
    case 16:
2013
        // XXX
2014
        break;
2015
#endif
2016
    }
2017
    helper_st_asi(addr, val, asi, size);
2018
}
2019

    
2020
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
2021
                            target_ulong val2, uint32_t asi)
2022
{
2023
    target_ulong ret;
2024

    
2025
    val1 &= 0xffffffffUL;
2026
    ret = helper_ld_asi(addr, asi, 4, 0);
2027
    ret &= 0xffffffffUL;
2028
    if (val1 == ret)
2029
        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
2030
    return ret;
2031
}
2032

    
2033
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
2034
                             target_ulong val2, uint32_t asi)
2035
{
2036
    target_ulong ret;
2037

    
2038
    ret = helper_ld_asi(addr, asi, 8, 0);
2039
    if (val1 == ret)
2040
        helper_st_asi(addr, val2, asi, 8);
2041
    return ret;
2042
}
2043
#endif /* TARGET_SPARC64 */
2044

    
2045
#ifndef TARGET_SPARC64
2046
void helper_rett(void)
2047
{
2048
    unsigned int cwp;
2049

    
2050
    if (env->psret == 1)
2051
        raise_exception(TT_ILL_INSN);
2052

    
2053
    env->psret = 1;
2054
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2055
    if (env->wim & (1 << cwp)) {
2056
        raise_exception(TT_WIN_UNF);
2057
    }
2058
    set_cwp(cwp);
2059
    env->psrs = env->psrps;
2060
}
2061
#endif
2062

    
2063
target_ulong helper_udiv(target_ulong a, target_ulong b)
2064
{
2065
    uint64_t x0;
2066
    uint32_t x1;
2067

    
2068
    x0 = a | ((uint64_t) (env->y) << 32);
2069
    x1 = b;
2070

    
2071
    if (x1 == 0) {
2072
        raise_exception(TT_DIV_ZERO);
2073
    }
2074

    
2075
    x0 = x0 / x1;
2076
    if (x0 > 0xffffffff) {
2077
        env->cc_src2 = 1;
2078
        return 0xffffffff;
2079
    } else {
2080
        env->cc_src2 = 0;
2081
        return x0;
2082
    }
2083
}
2084

    
2085
target_ulong helper_sdiv(target_ulong a, target_ulong b)
2086
{
2087
    int64_t x0;
2088
    int32_t x1;
2089

    
2090
    x0 = a | ((int64_t) (env->y) << 32);
2091
    x1 = b;
2092

    
2093
    if (x1 == 0) {
2094
        raise_exception(TT_DIV_ZERO);
2095
    }
2096

    
2097
    x0 = x0 / x1;
2098
    if ((int32_t) x0 != x0) {
2099
        env->cc_src2 = 1;
2100
        return x0 < 0? 0x80000000: 0x7fffffff;
2101
    } else {
2102
        env->cc_src2 = 0;
2103
        return x0;
2104
    }
2105
}
2106

    
2107
uint64_t helper_pack64(target_ulong high, target_ulong low)
2108
{
2109
    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
2110
}
2111

    
2112
void helper_ldfsr(void)
2113
{
2114
    int rnd_mode;
2115

    
2116
    PUT_FSR32(env, *((uint32_t *) &FT0));
2117
    switch (env->fsr & FSR_RD_MASK) {
2118
    case FSR_RD_NEAREST:
2119
        rnd_mode = float_round_nearest_even;
2120
        break;
2121
    default:
2122
    case FSR_RD_ZERO:
2123
        rnd_mode = float_round_to_zero;
2124
        break;
2125
    case FSR_RD_POS:
2126
        rnd_mode = float_round_up;
2127
        break;
2128
    case FSR_RD_NEG:
2129
        rnd_mode = float_round_down;
2130
        break;
2131
    }
2132
    set_float_rounding_mode(rnd_mode, &env->fp_status);
2133
}
2134

    
2135
void helper_stfsr(void)
2136
{
2137
    *((uint32_t *) &FT0) = GET_FSR32(env);
2138
}
2139

    
2140
void helper_debug(void)
2141
{
2142
    env->exception_index = EXCP_DEBUG;
2143
    cpu_loop_exit();
2144
}
2145

    
2146
#ifndef TARGET_SPARC64
2147
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2148
   handling ? */
2149
void helper_save(void)
2150
{
2151
    uint32_t cwp;
2152

    
2153
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2154
    if (env->wim & (1 << cwp)) {
2155
        raise_exception(TT_WIN_OVF);
2156
    }
2157
    set_cwp(cwp);
2158
}
2159

    
2160
void helper_restore(void)
2161
{
2162
    uint32_t cwp;
2163

    
2164
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2165
    if (env->wim & (1 << cwp)) {
2166
        raise_exception(TT_WIN_UNF);
2167
    }
2168
    set_cwp(cwp);
2169
}
2170

    
2171
void helper_wrpsr(target_ulong new_psr)
2172
{
2173
    if ((new_psr & PSR_CWP) >= NWINDOWS)
2174
        raise_exception(TT_ILL_INSN);
2175
    else
2176
        PUT_PSR(env, new_psr);
2177
}
2178

    
2179
target_ulong helper_rdpsr(void)
2180
{
2181
    return GET_PSR(env);
2182
}
2183

    
2184
#else
2185
/* XXX: use another pointer for %iN registers to avoid slow wrapping
2186
   handling ? */
2187
void helper_save(void)
2188
{
2189
    uint32_t cwp;
2190

    
2191
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2192
    if (env->cansave == 0) {
2193
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2194
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2195
                                    ((env->wstate & 0x7) << 2)));
2196
    } else {
2197
        if (env->cleanwin - env->canrestore == 0) {
2198
            // XXX Clean windows without trap
2199
            raise_exception(TT_CLRWIN);
2200
        } else {
2201
            env->cansave--;
2202
            env->canrestore++;
2203
            set_cwp(cwp);
2204
        }
2205
    }
2206
}
2207

    
2208
void helper_restore(void)
2209
{
2210
    uint32_t cwp;
2211

    
2212
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
2213
    if (env->canrestore == 0) {
2214
        raise_exception(TT_FILL | (env->otherwin != 0 ?
2215
                                   (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2216
                                   ((env->wstate & 0x7) << 2)));
2217
    } else {
2218
        env->cansave++;
2219
        env->canrestore--;
2220
        set_cwp(cwp);
2221
    }
2222
}
2223

    
2224
void helper_flushw(void)
2225
{
2226
    if (env->cansave != NWINDOWS - 2) {
2227
        raise_exception(TT_SPILL | (env->otherwin != 0 ?
2228
                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
2229
                                    ((env->wstate & 0x7) << 2)));
2230
    }
2231
}
2232

    
2233
void helper_saved(void)
2234
{
2235
    env->cansave++;
2236
    if (env->otherwin == 0)
2237
        env->canrestore--;
2238
    else
2239
        env->otherwin--;
2240
}
2241

    
2242
void helper_restored(void)
2243
{
2244
    env->canrestore++;
2245
    if (env->cleanwin < NWINDOWS - 1)
2246
        env->cleanwin++;
2247
    if (env->otherwin == 0)
2248
        env->cansave--;
2249
    else
2250
        env->otherwin--;
2251
}
2252

    
2253
target_ulong helper_rdccr(void)
2254
{
2255
    return GET_CCR(env);
2256
}
2257

    
2258
void helper_wrccr(target_ulong new_ccr)
2259
{
2260
    PUT_CCR(env, new_ccr);
2261
}
2262

    
2263
// CWP handling is reversed in V9, but we still use the V8 register
2264
// order.
2265
target_ulong helper_rdcwp(void)
2266
{
2267
    return GET_CWP64(env);
2268
}
2269

    
2270
void helper_wrcwp(target_ulong new_cwp)
2271
{
2272
    PUT_CWP64(env, new_cwp);
2273
}
2274

    
2275
// This function uses non-native bit order
2276
#define GET_FIELD(X, FROM, TO)                                  \
2277
    ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
2278

    
2279
// This function uses the order in the manuals, i.e. bit 0 is 2^0
2280
#define GET_FIELD_SP(X, FROM, TO)               \
2281
    GET_FIELD(X, 63 - (TO), 63 - (FROM))
2282

    
2283
target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
2284
{
2285
    return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
2286
        (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
2287
        (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
2288
        (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
2289
        (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
2290
        (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
2291
        (((pixel_addr >> 55) & 1) << 4) |
2292
        (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
2293
        GET_FIELD_SP(pixel_addr, 11, 12);
2294
}
2295

    
2296
target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
2297
{
2298
    uint64_t tmp;
2299

    
2300
    tmp = addr + offset;
2301
    env->gsr &= ~7ULL;
2302
    env->gsr |= tmp & 7ULL;
2303
    return tmp & ~7ULL;
2304
}
2305

    
2306
target_ulong helper_popc(target_ulong val)
2307
{
2308
    return ctpop64(val);
2309
}
2310

    
2311
static inline uint64_t *get_gregset(uint64_t pstate)
2312
{
2313
    switch (pstate) {
2314
    default:
2315
    case 0:
2316
        return env->bgregs;
2317
    case PS_AG:
2318
        return env->agregs;
2319
    case PS_MG:
2320
        return env->mgregs;
2321
    case PS_IG:
2322
        return env->igregs;
2323
    }
2324
}
2325

    
2326
static inline void change_pstate(uint64_t new_pstate)
2327
{
2328
    uint64_t pstate_regs, new_pstate_regs;
2329
    uint64_t *src, *dst;
2330

    
2331
    pstate_regs = env->pstate & 0xc01;
2332
    new_pstate_regs = new_pstate & 0xc01;
2333
    if (new_pstate_regs != pstate_regs) {
2334
        // Switch global register bank
2335
        src = get_gregset(new_pstate_regs);
2336
        dst = get_gregset(pstate_regs);
2337
        memcpy32(dst, env->gregs);
2338
        memcpy32(env->gregs, src);
2339
    }
2340
    env->pstate = new_pstate;
2341
}
2342

    
2343
void helper_wrpstate(target_ulong new_state)
2344
{
2345
    change_pstate(new_state & 0xf3f);
2346
}
2347

    
2348
void helper_done(void)
2349
{
2350
    env->tl--;
2351
    env->tsptr = &env->ts[env->tl];
2352
    env->pc = env->tsptr->tpc;
2353
    env->npc = env->tsptr->tnpc + 4;
2354
    PUT_CCR(env, env->tsptr->tstate >> 32);
2355
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2356
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2357
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2358
}
2359

    
2360
void helper_retry(void)
2361
{
2362
    env->tl--;
2363
    env->tsptr = &env->ts[env->tl];
2364
    env->pc = env->tsptr->tpc;
2365
    env->npc = env->tsptr->tnpc;
2366
    PUT_CCR(env, env->tsptr->tstate >> 32);
2367
    env->asi = (env->tsptr->tstate >> 24) & 0xff;
2368
    change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
2369
    PUT_CWP64(env, env->tsptr->tstate & 0xff);
2370
}
2371
#endif
2372

    
2373
void set_cwp(int new_cwp)
2374
{
2375
    /* put the modified wrap registers at their proper location */
2376
    if (env->cwp == (NWINDOWS - 1))
2377
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
2378
    env->cwp = new_cwp;
2379
    /* put the wrap registers at their temporary location */
2380
    if (new_cwp == (NWINDOWS - 1))
2381
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
2382
    env->regwptr = env->regbase + (new_cwp * 16);
2383
    REGWPTR = env->regwptr;
2384
}
2385

    
2386
void cpu_set_cwp(CPUState *env1, int new_cwp)
2387
{
2388
    CPUState *saved_env;
2389
#ifdef reg_REGWPTR
2390
    target_ulong *saved_regwptr;
2391
#endif
2392

    
2393
    saved_env = env;
2394
#ifdef reg_REGWPTR
2395
    saved_regwptr = REGWPTR;
2396
#endif
2397
    env = env1;
2398
    set_cwp(new_cwp);
2399
    env = saved_env;
2400
#ifdef reg_REGWPTR
2401
    REGWPTR = saved_regwptr;
2402
#endif
2403
}
2404

    
2405
#ifdef TARGET_SPARC64
2406
#ifdef DEBUG_PCALL
2407
static const char * const excp_names[0x50] = {
2408
    [TT_TFAULT] = "Instruction Access Fault",
2409
    [TT_TMISS] = "Instruction Access MMU Miss",
2410
    [TT_CODE_ACCESS] = "Instruction Access Error",
2411
    [TT_ILL_INSN] = "Illegal Instruction",
2412
    [TT_PRIV_INSN] = "Privileged Instruction",
2413
    [TT_NFPU_INSN] = "FPU Disabled",
2414
    [TT_FP_EXCP] = "FPU Exception",
2415
    [TT_TOVF] = "Tag Overflow",
2416
    [TT_CLRWIN] = "Clean Windows",
2417
    [TT_DIV_ZERO] = "Division By Zero",
2418
    [TT_DFAULT] = "Data Access Fault",
2419
    [TT_DMISS] = "Data Access MMU Miss",
2420
    [TT_DATA_ACCESS] = "Data Access Error",
2421
    [TT_DPROT] = "Data Protection Error",
2422
    [TT_UNALIGNED] = "Unaligned Memory Access",
2423
    [TT_PRIV_ACT] = "Privileged Action",
2424
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2425
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2426
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2427
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2428
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2429
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2430
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2431
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2432
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2433
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2434
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2435
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2436
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2437
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2438
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2439
};
2440
#endif
2441

    
2442
void do_interrupt(int intno)
2443
{
2444
#ifdef DEBUG_PCALL
2445
    if (loglevel & CPU_LOG_INT) {
2446
        static int count;
2447
        const char *name;
2448

    
2449
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
2450
            name = "Unknown";
2451
        else if (intno >= 0x100)
2452
            name = "Trap Instruction";
2453
        else if (intno >= 0xc0)
2454
            name = "Window Fill";
2455
        else if (intno >= 0x80)
2456
            name = "Window Spill";
2457
        else {
2458
            name = excp_names[intno];
2459
            if (!name)
2460
                name = "Unknown";
2461
        }
2462

    
2463
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
2464
                " SP=%016" PRIx64 "\n",
2465
                count, name, intno,
2466
                env->pc,
2467
                env->npc, env->regwptr[6]);
2468
        cpu_dump_state(env, logfile, fprintf, 0);
2469
#if 0
2470
        {
2471
            int i;
2472
            uint8_t *ptr;
2473

2474
            fprintf(logfile, "       code=");
2475
            ptr = (uint8_t *)env->pc;
2476
            for(i = 0; i < 16; i++) {
2477
                fprintf(logfile, " %02x", ldub(ptr + i));
2478
            }
2479
            fprintf(logfile, "\n");
2480
        }
2481
#endif
2482
        count++;
2483
    }
2484
#endif
2485
#if !defined(CONFIG_USER_ONLY)
2486
    if (env->tl == MAXTL) {
2487
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
2488
        return;
2489
    }
2490
#endif
2491
    env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
2492
        ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
2493
        GET_CWP64(env);
2494
    env->tsptr->tpc = env->pc;
2495
    env->tsptr->tnpc = env->npc;
2496
    env->tsptr->tt = intno;
2497
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
2498

    
2499
    if (intno == TT_CLRWIN)
2500
        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
2501
    else if ((intno & 0x1c0) == TT_SPILL)
2502
        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
2503
    else if ((intno & 0x1c0) == TT_FILL)
2504
        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
2505
    env->tbr &= ~0x7fffULL;
2506
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
2507
    if (env->tl < MAXTL - 1) {
2508
        env->tl++;
2509
    } else {
2510
        env->pstate |= PS_RED;
2511
        if (env->tl != MAXTL)
2512
            env->tl++;
2513
    }
2514
    env->tsptr = &env->ts[env->tl];
2515
    env->pc = env->tbr;
2516
    env->npc = env->pc + 4;
2517
    env->exception_index = 0;
2518
}
2519
#else
2520
#ifdef DEBUG_PCALL
2521
static const char * const excp_names[0x80] = {
2522
    [TT_TFAULT] = "Instruction Access Fault",
2523
    [TT_ILL_INSN] = "Illegal Instruction",
2524
    [TT_PRIV_INSN] = "Privileged Instruction",
2525
    [TT_NFPU_INSN] = "FPU Disabled",
2526
    [TT_WIN_OVF] = "Window Overflow",
2527
    [TT_WIN_UNF] = "Window Underflow",
2528
    [TT_UNALIGNED] = "Unaligned Memory Access",
2529
    [TT_FP_EXCP] = "FPU Exception",
2530
    [TT_DFAULT] = "Data Access Fault",
2531
    [TT_TOVF] = "Tag Overflow",
2532
    [TT_EXTINT | 0x1] = "External Interrupt 1",
2533
    [TT_EXTINT | 0x2] = "External Interrupt 2",
2534
    [TT_EXTINT | 0x3] = "External Interrupt 3",
2535
    [TT_EXTINT | 0x4] = "External Interrupt 4",
2536
    [TT_EXTINT | 0x5] = "External Interrupt 5",
2537
    [TT_EXTINT | 0x6] = "External Interrupt 6",
2538
    [TT_EXTINT | 0x7] = "External Interrupt 7",
2539
    [TT_EXTINT | 0x8] = "External Interrupt 8",
2540
    [TT_EXTINT | 0x9] = "External Interrupt 9",
2541
    [TT_EXTINT | 0xa] = "External Interrupt 10",
2542
    [TT_EXTINT | 0xb] = "External Interrupt 11",
2543
    [TT_EXTINT | 0xc] = "External Interrupt 12",
2544
    [TT_EXTINT | 0xd] = "External Interrupt 13",
2545
    [TT_EXTINT | 0xe] = "External Interrupt 14",
2546
    [TT_EXTINT | 0xf] = "External Interrupt 15",
2547
    [TT_TOVF] = "Tag Overflow",
2548
    [TT_CODE_ACCESS] = "Instruction Access Error",
2549
    [TT_DATA_ACCESS] = "Data Access Error",
2550
    [TT_DIV_ZERO] = "Division By Zero",
2551
    [TT_NCP_INSN] = "Coprocessor Disabled",
2552
};
2553
#endif
2554

    
2555
void do_interrupt(int intno)
2556
{
2557
    int cwp;
2558

    
2559
#ifdef DEBUG_PCALL
2560
    if (loglevel & CPU_LOG_INT) {
2561
        static int count;
2562
        const char *name;
2563

    
2564
        if (intno < 0 || intno >= 0x100)
2565
            name = "Unknown";
2566
        else if (intno >= 0x80)
2567
            name = "Trap Instruction";
2568
        else {
2569
            name = excp_names[intno];
2570
            if (!name)
2571
                name = "Unknown";
2572
        }
2573

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

2584
            fprintf(logfile, "       code=");
2585
            ptr = (uint8_t *)env->pc;
2586
            for(i = 0; i < 16; i++) {
2587
                fprintf(logfile, " %02x", ldub(ptr + i));
2588
            }
2589
            fprintf(logfile, "\n");
2590
        }
2591
#endif
2592
        count++;
2593
    }
2594
#endif
2595
#if !defined(CONFIG_USER_ONLY)
2596
    if (env->psret == 0) {
2597
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
2598
        return;
2599
    }
2600
#endif
2601
    env->psret = 0;
2602
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
2603
    set_cwp(cwp);
2604
    env->regwptr[9] = env->pc;
2605
    env->regwptr[10] = env->npc;
2606
    env->psrps = env->psrs;
2607
    env->psrs = 1;
2608
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
2609
    env->pc = env->tbr;
2610
    env->npc = env->pc + 4;
2611
    env->exception_index = 0;
2612
}
2613
#endif
2614

    
2615
#if !defined(CONFIG_USER_ONLY)
2616

    
2617
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2618
                                void *retaddr);
2619

    
2620
#define MMUSUFFIX _mmu
2621
#define ALIGNED_ONLY
2622
#ifdef __s390__
2623
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
2624
#else
2625
# define GETPC() (__builtin_return_address(0))
2626
#endif
2627

    
2628
#define SHIFT 0
2629
#include "softmmu_template.h"
2630

    
2631
#define SHIFT 1
2632
#include "softmmu_template.h"
2633

    
2634
#define SHIFT 2
2635
#include "softmmu_template.h"
2636

    
2637
#define SHIFT 3
2638
#include "softmmu_template.h"
2639

    
2640
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
2641
                                void *retaddr)
2642
{
2643
#ifdef DEBUG_UNALIGNED
2644
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
2645
#endif
2646
    raise_exception(TT_UNALIGNED);
2647
}
2648

    
2649
/* try to fill the TLB and return an exception if error. If retaddr is
2650
   NULL, it means that the function was called in C code (i.e. not
2651
   from generated code or from helper.c) */
2652
/* XXX: fix it to restore all registers */
2653
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
2654
{
2655
    TranslationBlock *tb;
2656
    int ret;
2657
    unsigned long pc;
2658
    CPUState *saved_env;
2659

    
2660
    /* XXX: hack to restore env in all cases, even if not called from
2661
       generated code */
2662
    saved_env = env;
2663
    env = cpu_single_env;
2664

    
2665
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
2666
    if (ret) {
2667
        if (retaddr) {
2668
            /* now we have a real cpu fault */
2669
            pc = (unsigned long)retaddr;
2670
            tb = tb_find_pc(pc);
2671
            if (tb) {
2672
                /* the PC is inside the translated code. It means that we have
2673
                   a virtual CPU fault */
2674
                cpu_restore_state(tb, env, pc, (void *)T2);
2675
            }
2676
        }
2677
        cpu_loop_exit();
2678
    }
2679
    env = saved_env;
2680
}
2681

    
2682
#endif
2683

    
2684
#ifndef TARGET_SPARC64
2685
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2686
                          int is_asi)
2687
{
2688
    CPUState *saved_env;
2689

    
2690
    /* XXX: hack to restore env in all cases, even if not called from
2691
       generated code */
2692
    saved_env = env;
2693
    env = cpu_single_env;
2694
#ifdef DEBUG_UNASSIGNED
2695
    if (is_asi)
2696
        printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2697
               TARGET_FMT_lx "\n",
2698
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2699
               env->pc);
2700
    else
2701
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2702
               TARGET_FMT_lx "\n",
2703
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2704
#endif
2705
    if (env->mmuregs[3]) /* Fault status register */
2706
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2707
    if (is_asi)
2708
        env->mmuregs[3] |= 1 << 16;
2709
    if (env->psrs)
2710
        env->mmuregs[3] |= 1 << 5;
2711
    if (is_exec)
2712
        env->mmuregs[3] |= 1 << 6;
2713
    if (is_write)
2714
        env->mmuregs[3] |= 1 << 7;
2715
    env->mmuregs[3] |= (5 << 2) | 2;
2716
    env->mmuregs[4] = addr; /* Fault address register */
2717
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2718
        if (is_exec)
2719
            raise_exception(TT_CODE_ACCESS);
2720
        else
2721
            raise_exception(TT_DATA_ACCESS);
2722
    }
2723
    env = saved_env;
2724
}
2725
#else
2726
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2727
                          int is_asi)
2728
{
2729
#ifdef DEBUG_UNASSIGNED
2730
    CPUState *saved_env;
2731

    
2732
    /* XXX: hack to restore env in all cases, even if not called from
2733
       generated code */
2734
    saved_env = env;
2735
    env = cpu_single_env;
2736
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2737
           addr, env->pc);
2738
    env = saved_env;
2739
#endif
2740
    if (is_exec)
2741
        raise_exception(TT_CODE_ACCESS);
2742
    else
2743
        raise_exception(TT_DATA_ACCESS);
2744
}
2745
#endif
2746