Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 1a2fb1c0

History | View | Annotate | Download (58.6 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 check_ieee_exceptions(void)
54
{
55
    target_ulong status;
56

    
57
    status = get_float_exception_flags(&env->fp_status);
58
    if (status) {
59
        /* Copy IEEE 754 flags into FSR */
60
        if (status & float_flag_invalid)
61
            env->fsr |= FSR_NVC;
62
        if (status & float_flag_overflow)
63
            env->fsr |= FSR_OFC;
64
        if (status & float_flag_underflow)
65
            env->fsr |= FSR_UFC;
66
        if (status & float_flag_divbyzero)
67
            env->fsr |= FSR_DZC;
68
        if (status & float_flag_inexact)
69
            env->fsr |= FSR_NXC;
70

    
71
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
72
            /* Unmasked exception, generate a trap */
73
            env->fsr |= FSR_FTT_IEEE_EXCP;
74
            raise_exception(TT_FP_EXCP);
75
        } else {
76
            /* Accumulate exceptions */
77
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
78
        }
79
    }
80
}
81

    
82
#ifdef USE_INT_TO_FLOAT_HELPERS
83
void do_fitos(void)
84
{
85
    set_float_exception_flags(0, &env->fp_status);
86
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
87
    check_ieee_exceptions();
88
}
89

    
90
void do_fitod(void)
91
{
92
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
93
}
94

    
95
#if defined(CONFIG_USER_ONLY)
96
void do_fitoq(void)
97
{
98
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
99
}
100
#endif
101

    
102
#ifdef TARGET_SPARC64
103
void do_fxtos(void)
104
{
105
    set_float_exception_flags(0, &env->fp_status);
106
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
107
    check_ieee_exceptions();
108
}
109

    
110
void do_fxtod(void)
111
{
112
    set_float_exception_flags(0, &env->fp_status);
113
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
114
    check_ieee_exceptions();
115
}
116

    
117
#if defined(CONFIG_USER_ONLY)
118
void do_fxtoq(void)
119
{
120
    set_float_exception_flags(0, &env->fp_status);
121
    QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status);
122
    check_ieee_exceptions();
123
}
124
#endif
125
#endif
126
#endif
127

    
128
void do_fabss(void)
129
{
130
    FT0 = float32_abs(FT1);
131
}
132

    
133
#ifdef TARGET_SPARC64
134
void do_fabsd(void)
135
{
136
    DT0 = float64_abs(DT1);
137
}
138

    
139
#if defined(CONFIG_USER_ONLY)
140
void do_fabsq(void)
141
{
142
    QT0 = float128_abs(QT1);
143
}
144
#endif
145
#endif
146

    
147
void do_fsqrts(void)
148
{
149
    set_float_exception_flags(0, &env->fp_status);
150
    FT0 = float32_sqrt(FT1, &env->fp_status);
151
    check_ieee_exceptions();
152
}
153

    
154
void do_fsqrtd(void)
155
{
156
    set_float_exception_flags(0, &env->fp_status);
157
    DT0 = float64_sqrt(DT1, &env->fp_status);
158
    check_ieee_exceptions();
159
}
160

    
161
#if defined(CONFIG_USER_ONLY)
162
void do_fsqrtq(void)
163
{
164
    set_float_exception_flags(0, &env->fp_status);
165
    QT0 = float128_sqrt(QT1, &env->fp_status);
166
    check_ieee_exceptions();
167
}
168
#endif
169

    
170
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
171
    void glue(do_, name) (void)                                         \
172
    {                                                                   \
173
        target_ulong new_fsr;                                           \
174
                                                                        \
175
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
176
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
177
        case float_relation_unordered:                                  \
178
            new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
179
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
180
                env->fsr |= new_fsr;                                    \
181
                env->fsr |= FSR_NVC;                                    \
182
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
183
                raise_exception(TT_FP_EXCP);                            \
184
            } else {                                                    \
185
                env->fsr |= FSR_NVA;                                    \
186
            }                                                           \
187
            break;                                                      \
188
        case float_relation_less:                                       \
189
            new_fsr = FSR_FCC0 << FS;                                   \
190
            break;                                                      \
191
        case float_relation_greater:                                    \
192
            new_fsr = FSR_FCC1 << FS;                                   \
193
            break;                                                      \
194
        default:                                                        \
195
            new_fsr = 0;                                                \
196
            break;                                                      \
197
        }                                                               \
198
        env->fsr |= new_fsr;                                            \
199
    }
200

    
201
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
202
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
203

    
204
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
205
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
206

    
207
#ifdef CONFIG_USER_ONLY
208
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
209
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
210
#endif
211

    
212
#ifdef TARGET_SPARC64
213
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
214
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
215

    
216
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
217
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
218

    
219
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
220
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
221

    
222
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
223
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
224

    
225
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
226
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
227

    
228
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
229
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
230
#ifdef CONFIG_USER_ONLY
231
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
232
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
233
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
234
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
235
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
236
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
237
#endif
238
#endif
239

    
240
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && defined(DEBUG_MXCC)
241
static void dump_mxcc(CPUState *env)
242
{
243
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
244
        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
245
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
246
           "          %016llx %016llx %016llx %016llx\n",
247
        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
248
        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
249
}
250
#endif
251

    
252
#if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
253
    && defined(DEBUG_ASI)
254
static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
255
                     uint64_t r1)
256
{
257
    switch (size)
258
    {
259
    case 1:
260
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
261
                    addr, asi, r1 & 0xff);
262
        break;
263
    case 2:
264
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
265
                    addr, asi, r1 & 0xffff);
266
        break;
267
    case 4:
268
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
269
                    addr, asi, r1 & 0xffffffff);
270
        break;
271
    case 8:
272
        DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
273
                    addr, asi, r1);
274
        break;
275
    }
276
}
277
#endif
278

    
279
#ifndef TARGET_SPARC64
280
#ifndef CONFIG_USER_ONLY
281
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
282
{
283
    uint64_t ret = 0;
284
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
285
    uint32_t last_addr = addr;
286
#endif
287

    
288
    switch (asi) {
289
    case 2: /* SuperSparc MXCC registers */
290
        switch (addr) {
291
        case 0x01c00a00: /* MXCC control register */
292
            if (size == 8)
293
                ret = env->mxccregs[3];
294
            else
295
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
296
            break;
297
        case 0x01c00a04: /* MXCC control register */
298
            if (size == 4)
299
                ret = env->mxccregs[3];
300
            else
301
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
302
            break;
303
        case 0x01c00c00: /* Module reset register */
304
            if (size == 8) {
305
                ret = env->mxccregs[5];
306
                // should we do something here?
307
            } else
308
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
309
            break;
310
        case 0x01c00f00: /* MBus port address register */
311
            if (size == 8)
312
                ret = env->mxccregs[7];
313
            else
314
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
315
            break;
316
        default:
317
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
318
            break;
319
        }
320
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, addr = %08x -> ret = %08x,"
321
                     "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
322
#ifdef DEBUG_MXCC
323
        dump_mxcc(env);
324
#endif
325
        break;
326
    case 3: /* MMU probe */
327
        {
328
            int mmulev;
329

    
330
            mmulev = (addr >> 8) & 15;
331
            if (mmulev > 4)
332
                ret = 0;
333
            else
334
                ret = mmu_probe(env, addr, mmulev);
335
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
336
                        addr, mmulev, ret);
337
        }
338
        break;
339
    case 4: /* read MMU regs */
340
        {
341
            int reg = (addr >> 8) & 0x1f;
342

    
343
            ret = env->mmuregs[reg];
344
            if (reg == 3) /* Fault status cleared on read */
345
                env->mmuregs[3] = 0;
346
            else if (reg == 0x13) /* Fault status read */
347
                ret = env->mmuregs[3];
348
            else if (reg == 0x14) /* Fault address read */
349
                ret = env->mmuregs[4];
350
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
351
        }
352
        break;
353
    case 5: // Turbosparc ITLB Diagnostic
354
    case 6: // Turbosparc DTLB Diagnostic
355
    case 7: // Turbosparc IOTLB Diagnostic
356
        break;
357
    case 9: /* Supervisor code access */
358
        switch(size) {
359
        case 1:
360
            ret = ldub_code(addr);
361
            break;
362
        case 2:
363
            ret = lduw_code(addr & ~1);
364
            break;
365
        default:
366
        case 4:
367
            ret = ldl_code(addr & ~3);
368
            break;
369
        case 8:
370
            ret = ldq_code(addr & ~7);
371
            break;
372
        }
373
        break;
374
    case 0xa: /* User data access */
375
        switch(size) {
376
        case 1:
377
            ret = ldub_user(addr);
378
            break;
379
        case 2:
380
            ret = lduw_user(addr & ~1);
381
            break;
382
        default:
383
        case 4:
384
            ret = ldl_user(addr & ~3);
385
            break;
386
        case 8:
387
            ret = ldq_user(addr & ~7);
388
            break;
389
        }
390
        break;
391
    case 0xb: /* Supervisor data access */
392
        switch(size) {
393
        case 1:
394
            ret = ldub_kernel(addr);
395
            break;
396
        case 2:
397
            ret = lduw_kernel(addr & ~1);
398
            break;
399
        default:
400
        case 4:
401
            ret = ldl_kernel(addr & ~3);
402
            break;
403
        case 8:
404
            ret = ldq_kernel(addr & ~7);
405
            break;
406
        }
407
        break;
408
    case 0xc: /* I-cache tag */
409
    case 0xd: /* I-cache data */
410
    case 0xe: /* D-cache tag */
411
    case 0xf: /* D-cache data */
412
        break;
413
    case 0x20: /* MMU passthrough */
414
        switch(size) {
415
        case 1:
416
            ret = ldub_phys(addr);
417
            break;
418
        case 2:
419
            ret = lduw_phys(addr & ~1);
420
            break;
421
        default:
422
        case 4:
423
            ret = ldl_phys(addr & ~3);
424
            break;
425
        case 8:
426
            ret = ldq_phys(addr & ~7);
427
            break;
428
        }
429
        break;
430
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
431
        switch(size) {
432
        case 1:
433
            ret = ldub_phys((target_phys_addr_t)addr
434
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
435
            break;
436
        case 2:
437
            ret = lduw_phys((target_phys_addr_t)(addr & ~1)
438
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
439
            break;
440
        default:
441
        case 4:
442
            ret = ldl_phys((target_phys_addr_t)(addr & ~3)
443
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
444
            break;
445
        case 8:
446
            ret = ldq_phys((target_phys_addr_t)(addr & ~7)
447
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
448
            break;
449
        }
450
        break;
451
    case 0x30: // Turbosparc secondary cache diagnostic
452
    case 0x31: // Turbosparc RAM snoop
453
    case 0x32: // Turbosparc page table descriptor diagnostic
454
    case 0x39: /* data cache diagnostic register */
455
        ret = 0;
456
        break;
457
    case 8: /* User code access, XXX */
458
    default:
459
        do_unassigned_access(addr, 0, 0, asi);
460
        ret = 0;
461
        break;
462
    }
463
    if (sign) {
464
        switch(size) {
465
        case 1:
466
            ret = (int8_t) ret;
467
            break;
468
        case 2:
469
            ret = (int16_t) ret;
470
            break;
471
        case 4:
472
            ret = (int32_t) ret;
473
            break;
474
        default:
475
            break;
476
        }
477
    }
478
#ifdef DEBUG_ASI
479
    dump_asi("read ", last_addr, asi, size, ret);
480
#endif
481
    return ret;
482
}
483

    
484
void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
485
{
486
    switch(asi) {
487
    case 2: /* SuperSparc MXCC registers */
488
        switch (addr) {
489
        case 0x01c00000: /* MXCC stream data register 0 */
490
            if (size == 8)
491
                env->mxccdata[0] = val;
492
            else
493
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
494
            break;
495
        case 0x01c00008: /* MXCC stream data register 1 */
496
            if (size == 8)
497
                env->mxccdata[1] = val;
498
            else
499
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
500
            break;
501
        case 0x01c00010: /* MXCC stream data register 2 */
502
            if (size == 8)
503
                env->mxccdata[2] = val;
504
            else
505
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
506
            break;
507
        case 0x01c00018: /* MXCC stream data register 3 */
508
            if (size == 8)
509
                env->mxccdata[3] = val;
510
            else
511
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
512
            break;
513
        case 0x01c00100: /* MXCC stream source */
514
            if (size == 8)
515
                env->mxccregs[0] = val;
516
            else
517
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
518
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
519
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
520
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
521
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
522
            break;
523
        case 0x01c00200: /* MXCC stream destination */
524
            if (size == 8)
525
                env->mxccregs[1] = val;
526
            else
527
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
528
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
529
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
530
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
531
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
532
            break;
533
        case 0x01c00a00: /* MXCC control register */
534
            if (size == 8)
535
                env->mxccregs[3] = val;
536
            else
537
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
538
            break;
539
        case 0x01c00a04: /* MXCC control register */
540
            if (size == 4)
541
                env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | val;
542
            else
543
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
544
            break;
545
        case 0x01c00e00: /* MXCC error register  */
546
            // writing a 1 bit clears the error
547
            if (size == 8)
548
                env->mxccregs[6] &= ~val;
549
            else
550
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
551
            break;
552
        case 0x01c00f00: /* MBus port address register */
553
            if (size == 8)
554
                env->mxccregs[7] = val;
555
            else
556
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr, size);
557
            break;
558
        default:
559
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr, size);
560
            break;
561
        }
562
        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi, size, addr, val);
563
#ifdef DEBUG_MXCC
564
        dump_mxcc(env);
565
#endif
566
        break;
567
    case 3: /* MMU flush */
568
        {
569
            int mmulev;
570

    
571
            mmulev = (addr >> 8) & 15;
572
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
573
            switch (mmulev) {
574
            case 0: // flush page
575
                tlb_flush_page(env, addr & 0xfffff000);
576
                break;
577
            case 1: // flush segment (256k)
578
            case 2: // flush region (16M)
579
            case 3: // flush context (4G)
580
            case 4: // flush entire
581
                tlb_flush(env, 1);
582
                break;
583
            default:
584
                break;
585
            }
586
#ifdef DEBUG_MMU
587
            dump_mmu(env);
588
#endif
589
        }
590
        break;
591
    case 4: /* write MMU regs */
592
        {
593
            int reg = (addr >> 8) & 0x1f;
594
            uint32_t oldreg;
595

    
596
            oldreg = env->mmuregs[reg];
597
            switch(reg) {
598
            case 0: // Control Register
599
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
600
                                    (val & 0x00ffffff);
601
                // Mappings generated during no-fault mode or MMU
602
                // disabled mode are invalid in normal mode
603
                if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
604
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
605
                    tlb_flush(env, 1);
606
                break;
607
            case 1: // Context Table Pointer Register
608
                env->mmuregs[reg] = val & env->mmu_ctpr_mask;
609
                break;
610
            case 2: // Context Register
611
                env->mmuregs[reg] = val & env->mmu_cxr_mask;
612
                if (oldreg != env->mmuregs[reg]) {
613
                    /* we flush when the MMU context changes because
614
                       QEMU has no MMU context support */
615
                    tlb_flush(env, 1);
616
                }
617
                break;
618
            case 3: // Synchronous Fault Status Register with Clear
619
            case 4: // Synchronous Fault Address Register
620
                break;
621
            case 0x10: // TLB Replacement Control Register
622
                env->mmuregs[reg] = val & env->mmu_trcr_mask;
623
                break;
624
            case 0x13: // Synchronous Fault Status Register with Read and Clear
625
                env->mmuregs[3] = val & env->mmu_sfsr_mask;
626
                break;
627
            case 0x14: // Synchronous Fault Address Register
628
                env->mmuregs[4] = val;
629
                break;
630
            default:
631
                env->mmuregs[reg] = val;
632
                break;
633
            }
634
            if (oldreg != env->mmuregs[reg]) {
635
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
636
            }
637
#ifdef DEBUG_MMU
638
            dump_mmu(env);
639
#endif
640
        }
641
        break;
642
    case 5: // Turbosparc ITLB Diagnostic
643
    case 6: // Turbosparc DTLB Diagnostic
644
    case 7: // Turbosparc IOTLB Diagnostic
645
        break;
646
    case 0xa: /* User data access */
647
        switch(size) {
648
        case 1:
649
            stb_user(addr, val);
650
            break;
651
        case 2:
652
            stw_user(addr & ~1, val);
653
            break;
654
        default:
655
        case 4:
656
            stl_user(addr & ~3, val);
657
            break;
658
        case 8:
659
            stq_user(addr & ~7, val);
660
            break;
661
        }
662
        break;
663
    case 0xb: /* Supervisor data access */
664
        switch(size) {
665
        case 1:
666
            stb_kernel(addr, val);
667
            break;
668
        case 2:
669
            stw_kernel(addr & ~1, val);
670
            break;
671
        default:
672
        case 4:
673
            stl_kernel(addr & ~3, val);
674
            break;
675
        case 8:
676
            stq_kernel(addr & ~7, val);
677
            break;
678
        }
679
        break;
680
    case 0xc: /* I-cache tag */
681
    case 0xd: /* I-cache data */
682
    case 0xe: /* D-cache tag */
683
    case 0xf: /* D-cache data */
684
    case 0x10: /* I/D-cache flush page */
685
    case 0x11: /* I/D-cache flush segment */
686
    case 0x12: /* I/D-cache flush region */
687
    case 0x13: /* I/D-cache flush context */
688
    case 0x14: /* I/D-cache flush user */
689
        break;
690
    case 0x17: /* Block copy, sta access */
691
        {
692
            // val = src
693
            // addr = dst
694
            // copy 32 bytes
695
            unsigned int i;
696
            uint32_t src = val & ~3, dst = addr & ~3, temp;
697

    
698
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
699
                temp = ldl_kernel(src);
700
                stl_kernel(dst, temp);
701
            }
702
        }
703
        break;
704
    case 0x1f: /* Block fill, stda access */
705
        {
706
            // addr = dst
707
            // fill 32 bytes with val
708
            unsigned int i;
709
            uint32_t dst = addr & 7;
710

    
711
            for (i = 0; i < 32; i += 8, dst += 8)
712
                stq_kernel(dst, val);
713
        }
714
        break;
715
    case 0x20: /* MMU passthrough */
716
        {
717
            switch(size) {
718
            case 1:
719
                stb_phys(addr, val);
720
                break;
721
            case 2:
722
                stw_phys(addr & ~1, val);
723
                break;
724
            case 4:
725
            default:
726
                stl_phys(addr & ~3, val);
727
                break;
728
            case 8:
729
                stq_phys(addr & ~7, val);
730
                break;
731
            }
732
        }
733
        break;
734
    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
735
        {
736
            switch(size) {
737
            case 1:
738
                stb_phys((target_phys_addr_t)addr
739
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
740
                break;
741
            case 2:
742
                stw_phys((target_phys_addr_t)(addr & ~1)
743
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
744
                break;
745
            case 4:
746
            default:
747
                stl_phys((target_phys_addr_t)(addr & ~3)
748
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
749
                break;
750
            case 8:
751
                stq_phys((target_phys_addr_t)(addr & ~7)
752
                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);
753
                break;
754
            }
755
        }
756
        break;
757
    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
758
    case 0x31: // store buffer data, Ross RT620 I-cache flush or
759
               // Turbosparc snoop RAM
760
    case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
761
    case 0x36: /* I-cache flash clear */
762
    case 0x37: /* D-cache flash clear */
763
    case 0x38: /* breakpoint diagnostics */
764
    case 0x4c: /* breakpoint action */
765
        break;
766
    case 8: /* User code access, XXX */
767
    case 9: /* Supervisor code access, XXX */
768
    default:
769
        do_unassigned_access(addr, 1, 0, asi);
770
        break;
771
    }
772
#ifdef DEBUG_ASI
773
    dump_asi("write", addr, asi, size, val);
774
#endif
775
}
776

    
777
#endif /* CONFIG_USER_ONLY */
778
#else /* TARGET_SPARC64 */
779

    
780
#ifdef CONFIG_USER_ONLY
781
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
782
{
783
    uint64_t ret = 0;
784
#if defined(DEBUG_ASI)
785
    target_ulong last_addr = addr;
786
#endif
787

    
788
    if (asi < 0x80)
789
        raise_exception(TT_PRIV_ACT);
790

    
791
    switch (asi) {
792
    case 0x80: // Primary
793
    case 0x82: // Primary no-fault
794
    case 0x88: // Primary LE
795
    case 0x8a: // Primary no-fault LE
796
        {
797
            switch(size) {
798
            case 1:
799
                ret = ldub_raw(addr);
800
                break;
801
            case 2:
802
                ret = lduw_raw(addr & ~1);
803
                break;
804
            case 4:
805
                ret = ldl_raw(addr & ~3);
806
                break;
807
            default:
808
            case 8:
809
                ret = ldq_raw(addr & ~7);
810
                break;
811
            }
812
        }
813
        break;
814
    case 0x81: // Secondary
815
    case 0x83: // Secondary no-fault
816
    case 0x89: // Secondary LE
817
    case 0x8b: // Secondary no-fault LE
818
        // XXX
819
        break;
820
    default:
821
        break;
822
    }
823

    
824
    /* Convert from little endian */
825
    switch (asi) {
826
    case 0x88: // Primary LE
827
    case 0x89: // Secondary LE
828
    case 0x8a: // Primary no-fault LE
829
    case 0x8b: // Secondary no-fault LE
830
        switch(size) {
831
        case 2:
832
            ret = bswap16(ret);
833
            break;
834
        case 4:
835
            ret = bswap32(ret);
836
            break;
837
        case 8:
838
            ret = bswap64(ret);
839
            break;
840
        default:
841
            break;
842
        }
843
    default:
844
        break;
845
    }
846

    
847
    /* Convert to signed number */
848
    if (sign) {
849
        switch(size) {
850
        case 1:
851
            ret = (int8_t) ret;
852
            break;
853
        case 2:
854
            ret = (int16_t) ret;
855
            break;
856
        case 4:
857
            ret = (int32_t) ret;
858
            break;
859
        default:
860
            break;
861
        }
862
    }
863
#ifdef DEBUG_ASI
864
    dump_asi("read ", last_addr, asi, size, ret);
865
#endif
866
    return ret;
867
}
868

    
869
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
870
{
871
#ifdef DEBUG_ASI
872
    dump_asi("write", addr, asi, size, val);
873
#endif
874
    if (asi < 0x80)
875
        raise_exception(TT_PRIV_ACT);
876

    
877
    /* Convert to little endian */
878
    switch (asi) {
879
    case 0x88: // Primary LE
880
    case 0x89: // Secondary LE
881
        switch(size) {
882
        case 2:
883
            addr = bswap16(addr);
884
            break;
885
        case 4:
886
            addr = bswap32(addr);
887
            break;
888
        case 8:
889
            addr = bswap64(addr);
890
            break;
891
        default:
892
            break;
893
        }
894
    default:
895
        break;
896
    }
897

    
898
    switch(asi) {
899
    case 0x80: // Primary
900
    case 0x88: // Primary LE
901
        {
902
            switch(size) {
903
            case 1:
904
                stb_raw(addr, val);
905
                break;
906
            case 2:
907
                stw_raw(addr & ~1, val);
908
                break;
909
            case 4:
910
                stl_raw(addr & ~3, val);
911
                break;
912
            case 8:
913
            default:
914
                stq_raw(addr & ~7, val);
915
                break;
916
            }
917
        }
918
        break;
919
    case 0x81: // Secondary
920
    case 0x89: // Secondary LE
921
        // XXX
922
        return;
923

    
924
    case 0x82: // Primary no-fault, RO
925
    case 0x83: // Secondary no-fault, RO
926
    case 0x8a: // Primary no-fault LE, RO
927
    case 0x8b: // Secondary no-fault LE, RO
928
    default:
929
        do_unassigned_access(addr, 1, 0, 1);
930
        return;
931
    }
932
}
933

    
934
#else /* CONFIG_USER_ONLY */
935

    
936
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
937
{
938
    uint64_t ret = 0;
939
#if defined(DEBUG_ASI)
940
    target_ulong last_addr = addr;
941
#endif
942

    
943
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
944
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
945
        raise_exception(TT_PRIV_ACT);
946

    
947
    switch (asi) {
948
    case 0x10: // As if user primary
949
    case 0x18: // As if user primary LE
950
    case 0x80: // Primary
951
    case 0x82: // Primary no-fault
952
    case 0x88: // Primary LE
953
    case 0x8a: // Primary no-fault LE
954
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
955
            if (env->hpstate & HS_PRIV) {
956
                switch(size) {
957
                case 1:
958
                    ret = ldub_hypv(addr);
959
                    break;
960
                case 2:
961
                    ret = lduw_hypv(addr & ~1);
962
                    break;
963
                case 4:
964
                    ret = ldl_hypv(addr & ~3);
965
                    break;
966
                default:
967
                case 8:
968
                    ret = ldq_hypv(addr & ~7);
969
                    break;
970
                }
971
            } else {
972
                switch(size) {
973
                case 1:
974
                    ret = ldub_kernel(addr);
975
                    break;
976
                case 2:
977
                    ret = lduw_kernel(addr & ~1);
978
                    break;
979
                case 4:
980
                    ret = ldl_kernel(addr & ~3);
981
                    break;
982
                default:
983
                case 8:
984
                    ret = ldq_kernel(addr & ~7);
985
                    break;
986
                }
987
            }
988
        } else {
989
            switch(size) {
990
            case 1:
991
                ret = ldub_user(addr);
992
                break;
993
            case 2:
994
                ret = lduw_user(addr & ~1);
995
                break;
996
            case 4:
997
                ret = ldl_user(addr & ~3);
998
                break;
999
            default:
1000
            case 8:
1001
                ret = ldq_user(addr & ~7);
1002
                break;
1003
            }
1004
        }
1005
        break;
1006
    case 0x14: // Bypass
1007
    case 0x15: // Bypass, non-cacheable
1008
    case 0x1c: // Bypass LE
1009
    case 0x1d: // Bypass, non-cacheable LE
1010
        {
1011
            switch(size) {
1012
            case 1:
1013
                ret = ldub_phys(addr);
1014
                break;
1015
            case 2:
1016
                ret = lduw_phys(addr & ~1);
1017
                break;
1018
            case 4:
1019
                ret = ldl_phys(addr & ~3);
1020
                break;
1021
            default:
1022
            case 8:
1023
                ret = ldq_phys(addr & ~7);
1024
                break;
1025
            }
1026
            break;
1027
        }
1028
    case 0x04: // Nucleus
1029
    case 0x0c: // Nucleus Little Endian (LE)
1030
    case 0x11: // As if user secondary
1031
    case 0x19: // As if user secondary LE
1032
    case 0x24: // Nucleus quad LDD 128 bit atomic
1033
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1034
    case 0x4a: // UPA config
1035
    case 0x81: // Secondary
1036
    case 0x83: // Secondary no-fault
1037
    case 0x89: // Secondary LE
1038
    case 0x8b: // Secondary no-fault LE
1039
        // XXX
1040
        break;
1041
    case 0x45: // LSU
1042
        ret = env->lsu;
1043
        break;
1044
    case 0x50: // I-MMU regs
1045
        {
1046
            int reg = (addr >> 3) & 0xf;
1047

    
1048
            ret = env->immuregs[reg];
1049
            break;
1050
        }
1051
    case 0x51: // I-MMU 8k TSB pointer
1052
    case 0x52: // I-MMU 64k TSB pointer
1053
    case 0x55: // I-MMU data access
1054
        // XXX
1055
        break;
1056
    case 0x56: // I-MMU tag read
1057
        {
1058
            unsigned int i;
1059

    
1060
            for (i = 0; i < 64; i++) {
1061
                // Valid, ctx match, vaddr match
1062
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1063
                    env->itlb_tag[i] == addr) {
1064
                    ret = env->itlb_tag[i];
1065
                    break;
1066
                }
1067
            }
1068
            break;
1069
        }
1070
    case 0x58: // D-MMU regs
1071
        {
1072
            int reg = (addr >> 3) & 0xf;
1073

    
1074
            ret = env->dmmuregs[reg];
1075
            break;
1076
        }
1077
    case 0x5e: // D-MMU tag read
1078
        {
1079
            unsigned int i;
1080

    
1081
            for (i = 0; i < 64; i++) {
1082
                // Valid, ctx match, vaddr match
1083
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1084
                    env->dtlb_tag[i] == addr) {
1085
                    ret = env->dtlb_tag[i];
1086
                    break;
1087
                }
1088
            }
1089
            break;
1090
        }
1091
    case 0x59: // D-MMU 8k TSB pointer
1092
    case 0x5a: // D-MMU 64k TSB pointer
1093
    case 0x5b: // D-MMU data pointer
1094
    case 0x5d: // D-MMU data access
1095
    case 0x48: // Interrupt dispatch, RO
1096
    case 0x49: // Interrupt data receive
1097
    case 0x7f: // Incoming interrupt vector, RO
1098
        // XXX
1099
        break;
1100
    case 0x54: // I-MMU data in, WO
1101
    case 0x57: // I-MMU demap, WO
1102
    case 0x5c: // D-MMU data in, WO
1103
    case 0x5f: // D-MMU demap, WO
1104
    case 0x77: // Interrupt vector, WO
1105
    default:
1106
        do_unassigned_access(addr, 0, 0, 1);
1107
        ret = 0;
1108
        break;
1109
    }
1110

    
1111
    /* Convert from little endian */
1112
    switch (asi) {
1113
    case 0x0c: // Nucleus Little Endian (LE)
1114
    case 0x18: // As if user primary LE
1115
    case 0x19: // As if user secondary LE
1116
    case 0x1c: // Bypass LE
1117
    case 0x1d: // Bypass, non-cacheable LE
1118
    case 0x88: // Primary LE
1119
    case 0x89: // Secondary LE
1120
    case 0x8a: // Primary no-fault LE
1121
    case 0x8b: // Secondary no-fault LE
1122
        switch(size) {
1123
        case 2:
1124
            ret = bswap16(ret);
1125
            break;
1126
        case 4:
1127
            ret = bswap32(ret);
1128
            break;
1129
        case 8:
1130
            ret = bswap64(ret);
1131
            break;
1132
        default:
1133
            break;
1134
        }
1135
    default:
1136
        break;
1137
    }
1138

    
1139
    /* Convert to signed number */
1140
    if (sign) {
1141
        switch(size) {
1142
        case 1:
1143
            ret = (int8_t) ret;
1144
            break;
1145
        case 2:
1146
            ret = (int16_t) ret;
1147
            break;
1148
        case 4:
1149
            ret = (int32_t) ret;
1150
            break;
1151
        default:
1152
            break;
1153
        }
1154
    }
1155
#ifdef DEBUG_ASI
1156
    dump_asi("read ", last_addr, asi, size, ret);
1157
#endif
1158
    return ret;
1159
}
1160

    
1161
void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1162
{
1163
#ifdef DEBUG_ASI
1164
    dump_asi("write", addr, asi, size, val);
1165
#endif
1166
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1167
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1168
        raise_exception(TT_PRIV_ACT);
1169

    
1170
    /* Convert to little endian */
1171
    switch (asi) {
1172
    case 0x0c: // Nucleus Little Endian (LE)
1173
    case 0x18: // As if user primary LE
1174
    case 0x19: // As if user secondary LE
1175
    case 0x1c: // Bypass LE
1176
    case 0x1d: // Bypass, non-cacheable LE
1177
    case 0x88: // Primary LE
1178
    case 0x89: // Secondary LE
1179
        switch(size) {
1180
        case 2:
1181
            addr = bswap16(addr);
1182
            break;
1183
        case 4:
1184
            addr = bswap32(addr);
1185
            break;
1186
        case 8:
1187
            addr = bswap64(addr);
1188
            break;
1189
        default:
1190
            break;
1191
        }
1192
    default:
1193
        break;
1194
    }
1195

    
1196
    switch(asi) {
1197
    case 0x10: // As if user primary
1198
    case 0x18: // As if user primary LE
1199
    case 0x80: // Primary
1200
    case 0x88: // Primary LE
1201
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1202
            if (env->hpstate & HS_PRIV) {
1203
                switch(size) {
1204
                case 1:
1205
                    stb_hypv(addr, val);
1206
                    break;
1207
                case 2:
1208
                    stw_hypv(addr & ~1, val);
1209
                    break;
1210
                case 4:
1211
                    stl_hypv(addr & ~3, val);
1212
                    break;
1213
                case 8:
1214
                default:
1215
                    stq_hypv(addr & ~7, val);
1216
                    break;
1217
                }
1218
            } else {
1219
                switch(size) {
1220
                case 1:
1221
                    stb_kernel(addr, val);
1222
                    break;
1223
                case 2:
1224
                    stw_kernel(addr & ~1, val);
1225
                    break;
1226
                case 4:
1227
                    stl_kernel(addr & ~3, val);
1228
                    break;
1229
                case 8:
1230
                default:
1231
                    stq_kernel(addr & ~7, val);
1232
                    break;
1233
                }
1234
            }
1235
        } else {
1236
            switch(size) {
1237
            case 1:
1238
                stb_user(addr, val);
1239
                break;
1240
            case 2:
1241
                stw_user(addr & ~1, val);
1242
                break;
1243
            case 4:
1244
                stl_user(addr & ~3, val);
1245
                break;
1246
            case 8:
1247
            default:
1248
                stq_user(addr & ~7, val);
1249
                break;
1250
            }
1251
        }
1252
        break;
1253
    case 0x14: // Bypass
1254
    case 0x15: // Bypass, non-cacheable
1255
    case 0x1c: // Bypass LE
1256
    case 0x1d: // Bypass, non-cacheable LE
1257
        {
1258
            switch(size) {
1259
            case 1:
1260
                stb_phys(addr, val);
1261
                break;
1262
            case 2:
1263
                stw_phys(addr & ~1, val);
1264
                break;
1265
            case 4:
1266
                stl_phys(addr & ~3, val);
1267
                break;
1268
            case 8:
1269
            default:
1270
                stq_phys(addr & ~7, val);
1271
                break;
1272
            }
1273
        }
1274
        return;
1275
    case 0x04: // Nucleus
1276
    case 0x0c: // Nucleus Little Endian (LE)
1277
    case 0x11: // As if user secondary
1278
    case 0x19: // As if user secondary LE
1279
    case 0x24: // Nucleus quad LDD 128 bit atomic
1280
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1281
    case 0x4a: // UPA config
1282
    case 0x81: // Secondary
1283
    case 0x89: // Secondary LE
1284
        // XXX
1285
        return;
1286
    case 0x45: // LSU
1287
        {
1288
            uint64_t oldreg;
1289

    
1290
            oldreg = env->lsu;
1291
            env->lsu = val & (DMMU_E | IMMU_E);
1292
            // Mappings generated during D/I MMU disabled mode are
1293
            // invalid in normal mode
1294
            if (oldreg != env->lsu) {
1295
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1296
#ifdef DEBUG_MMU
1297
                dump_mmu(env);
1298
#endif
1299
                tlb_flush(env, 1);
1300
            }
1301
            return;
1302
        }
1303
    case 0x50: // I-MMU regs
1304
        {
1305
            int reg = (addr >> 3) & 0xf;
1306
            uint64_t oldreg;
1307

    
1308
            oldreg = env->immuregs[reg];
1309
            switch(reg) {
1310
            case 0: // RO
1311
            case 4:
1312
                return;
1313
            case 1: // Not in I-MMU
1314
            case 2:
1315
            case 7:
1316
            case 8:
1317
                return;
1318
            case 3: // SFSR
1319
                if ((val & 1) == 0)
1320
                    val = 0; // Clear SFSR
1321
                break;
1322
            case 5: // TSB access
1323
            case 6: // Tag access
1324
            default:
1325
                break;
1326
            }
1327
            env->immuregs[reg] = val;
1328
            if (oldreg != env->immuregs[reg]) {
1329
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1330
            }
1331
#ifdef DEBUG_MMU
1332
            dump_mmu(env);
1333
#endif
1334
            return;
1335
        }
1336
    case 0x54: // I-MMU data in
1337
        {
1338
            unsigned int i;
1339

    
1340
            // Try finding an invalid entry
1341
            for (i = 0; i < 64; i++) {
1342
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1343
                    env->itlb_tag[i] = env->immuregs[6];
1344
                    env->itlb_tte[i] = val;
1345
                    return;
1346
                }
1347
            }
1348
            // Try finding an unlocked entry
1349
            for (i = 0; i < 64; i++) {
1350
                if ((env->itlb_tte[i] & 0x40) == 0) {
1351
                    env->itlb_tag[i] = env->immuregs[6];
1352
                    env->itlb_tte[i] = val;
1353
                    return;
1354
                }
1355
            }
1356
            // error state?
1357
            return;
1358
        }
1359
    case 0x55: // I-MMU data access
1360
        {
1361
            unsigned int i = (addr >> 3) & 0x3f;
1362

    
1363
            env->itlb_tag[i] = env->immuregs[6];
1364
            env->itlb_tte[i] = val;
1365
            return;
1366
        }
1367
    case 0x57: // I-MMU demap
1368
        // XXX
1369
        return;
1370
    case 0x58: // D-MMU regs
1371
        {
1372
            int reg = (addr >> 3) & 0xf;
1373
            uint64_t oldreg;
1374

    
1375
            oldreg = env->dmmuregs[reg];
1376
            switch(reg) {
1377
            case 0: // RO
1378
            case 4:
1379
                return;
1380
            case 3: // SFSR
1381
                if ((val & 1) == 0) {
1382
                    val = 0; // Clear SFSR, Fault address
1383
                    env->dmmuregs[4] = 0;
1384
                }
1385
                env->dmmuregs[reg] = val;
1386
                break;
1387
            case 1: // Primary context
1388
            case 2: // Secondary context
1389
            case 5: // TSB access
1390
            case 6: // Tag access
1391
            case 7: // Virtual Watchpoint
1392
            case 8: // Physical Watchpoint
1393
            default:
1394
                break;
1395
            }
1396
            env->dmmuregs[reg] = val;
1397
            if (oldreg != env->dmmuregs[reg]) {
1398
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1399
            }
1400
#ifdef DEBUG_MMU
1401
            dump_mmu(env);
1402
#endif
1403
            return;
1404
        }
1405
    case 0x5c: // D-MMU data in
1406
        {
1407
            unsigned int i;
1408

    
1409
            // Try finding an invalid entry
1410
            for (i = 0; i < 64; i++) {
1411
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1412
                    env->dtlb_tag[i] = env->dmmuregs[6];
1413
                    env->dtlb_tte[i] = val;
1414
                    return;
1415
                }
1416
            }
1417
            // Try finding an unlocked entry
1418
            for (i = 0; i < 64; i++) {
1419
                if ((env->dtlb_tte[i] & 0x40) == 0) {
1420
                    env->dtlb_tag[i] = env->dmmuregs[6];
1421
                    env->dtlb_tte[i] = val;
1422
                    return;
1423
                }
1424
            }
1425
            // error state?
1426
            return;
1427
        }
1428
    case 0x5d: // D-MMU data access
1429
        {
1430
            unsigned int i = (addr >> 3) & 0x3f;
1431

    
1432
            env->dtlb_tag[i] = env->dmmuregs[6];
1433
            env->dtlb_tte[i] = val;
1434
            return;
1435
        }
1436
    case 0x5f: // D-MMU demap
1437
    case 0x49: // Interrupt data receive
1438
        // XXX
1439
        return;
1440
    case 0x51: // I-MMU 8k TSB pointer, RO
1441
    case 0x52: // I-MMU 64k TSB pointer, RO
1442
    case 0x56: // I-MMU tag read, RO
1443
    case 0x59: // D-MMU 8k TSB pointer, RO
1444
    case 0x5a: // D-MMU 64k TSB pointer, RO
1445
    case 0x5b: // D-MMU data pointer, RO
1446
    case 0x5e: // D-MMU tag read, RO
1447
    case 0x48: // Interrupt dispatch, RO
1448
    case 0x7f: // Incoming interrupt vector, RO
1449
    case 0x82: // Primary no-fault, RO
1450
    case 0x83: // Secondary no-fault, RO
1451
    case 0x8a: // Primary no-fault LE, RO
1452
    case 0x8b: // Secondary no-fault LE, RO
1453
    default:
1454
        do_unassigned_access(addr, 1, 0, 1);
1455
        return;
1456
    }
1457
}
1458
#endif /* CONFIG_USER_ONLY */
1459

    
1460
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
1461
{
1462
    unsigned int i;
1463
    target_ulong val;
1464

    
1465
    switch (asi) {
1466
    case 0xf0: // Block load primary
1467
    case 0xf1: // Block load secondary
1468
    case 0xf8: // Block load primary LE
1469
    case 0xf9: // Block load secondary LE
1470
        if (rd & 7) {
1471
            raise_exception(TT_ILL_INSN);
1472
            return;
1473
        }
1474
        if (addr & 0x3f) {
1475
            raise_exception(TT_UNALIGNED);
1476
            return;
1477
        }
1478
        for (i = 0; i < 16; i++) {
1479
            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, 0);
1480
            addr += 4;
1481
        }
1482

    
1483
        return;
1484
    default:
1485
        break;
1486
    }
1487

    
1488
    val = helper_ld_asi(addr, asi, size, 0);
1489
    switch(size) {
1490
    default:
1491
    case 4:
1492
        *((uint32_t *)&FT0) = val;
1493
        break;
1494
    case 8:
1495
        *((int64_t *)&DT0) = val;
1496
        break;
1497
#if defined(CONFIG_USER_ONLY)
1498
    case 16:
1499
        // XXX
1500
        break;
1501
#endif
1502
    }
1503
}
1504

    
1505
void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
1506
{
1507
    unsigned int i;
1508
    target_ulong val = 0;
1509

    
1510
    switch (asi) {
1511
    case 0xf0: // Block store primary
1512
    case 0xf1: // Block store secondary
1513
    case 0xf8: // Block store primary LE
1514
    case 0xf9: // Block store secondary LE
1515
        if (rd & 7) {
1516
            raise_exception(TT_ILL_INSN);
1517
            return;
1518
        }
1519
        if (addr & 0x3f) {
1520
            raise_exception(TT_UNALIGNED);
1521
            return;
1522
        }
1523
        for (i = 0; i < 16; i++) {
1524
            val = *(uint32_t *)&env->fpr[rd++];
1525
            helper_st_asi(addr, val, asi & 0x8f, 4);
1526
            addr += 4;
1527
        }
1528

    
1529
        return;
1530
    default:
1531
        break;
1532
    }
1533

    
1534
    switch(size) {
1535
    default:
1536
    case 4:
1537
        val = *((uint32_t *)&FT0);
1538
        break;
1539
    case 8:
1540
        val = *((int64_t *)&DT0);
1541
        break;
1542
#if defined(CONFIG_USER_ONLY)
1543
    case 16:
1544
        // XXX
1545
        break;
1546
#endif
1547
    }
1548
    helper_st_asi(addr, val, asi, size);
1549
}
1550

    
1551
target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
1552
                            target_ulong val2, uint32_t asi)
1553
{
1554
    target_ulong ret;
1555

    
1556
    val1 &= 0xffffffffUL;
1557
    ret = helper_ld_asi(addr, asi, 4, 0);
1558
    ret &= 0xffffffffUL;
1559
    if (val1 == ret)
1560
        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);
1561
    return ret;
1562
}
1563

    
1564
target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
1565
                             target_ulong val2, uint32_t asi)
1566
{
1567
    target_ulong ret;
1568

    
1569
    ret = helper_ld_asi(addr, asi, 8, 0);
1570
    if (val1 == ret)
1571
        helper_st_asi(addr, val2, asi, 8);
1572
    return ret;
1573
}
1574
#endif /* TARGET_SPARC64 */
1575

    
1576
#ifndef TARGET_SPARC64
1577
void helper_rett(void)
1578
{
1579
    unsigned int cwp;
1580

    
1581
    if (env->psret == 1)
1582
        raise_exception(TT_ILL_INSN);
1583

    
1584
    env->psret = 1;
1585
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
1586
    if (env->wim & (1 << cwp)) {
1587
        raise_exception(TT_WIN_UNF);
1588
    }
1589
    set_cwp(cwp);
1590
    env->psrs = env->psrps;
1591
}
1592
#endif
1593

    
1594
uint64_t helper_pack64(target_ulong high, target_ulong low)
1595
{
1596
    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);
1597
}
1598

    
1599
void helper_ldfsr(void)
1600
{
1601
    int rnd_mode;
1602
    switch (env->fsr & FSR_RD_MASK) {
1603
    case FSR_RD_NEAREST:
1604
        rnd_mode = float_round_nearest_even;
1605
        break;
1606
    default:
1607
    case FSR_RD_ZERO:
1608
        rnd_mode = float_round_to_zero;
1609
        break;
1610
    case FSR_RD_POS:
1611
        rnd_mode = float_round_up;
1612
        break;
1613
    case FSR_RD_NEG:
1614
        rnd_mode = float_round_down;
1615
        break;
1616
    }
1617
    set_float_rounding_mode(rnd_mode, &env->fp_status);
1618
}
1619

    
1620
void helper_debug()
1621
{
1622
    env->exception_index = EXCP_DEBUG;
1623
    cpu_loop_exit();
1624
}
1625

    
1626
#ifndef TARGET_SPARC64
1627
void helper_wrpsr(target_ulong new_psr)
1628
{
1629
    if ((new_psr & PSR_CWP) >= NWINDOWS)
1630
        raise_exception(TT_ILL_INSN);
1631
    else
1632
        PUT_PSR(env, new_psr);
1633
}
1634

    
1635
target_ulong helper_rdpsr(void)
1636
{
1637
    return GET_PSR(env);
1638
}
1639

    
1640
#else
1641

    
1642
target_ulong helper_popc(target_ulong val)
1643
{
1644
    return ctpop64(val);
1645
}
1646

    
1647
static inline uint64_t *get_gregset(uint64_t pstate)
1648
{
1649
    switch (pstate) {
1650
    default:
1651
    case 0:
1652
        return env->bgregs;
1653
    case PS_AG:
1654
        return env->agregs;
1655
    case PS_MG:
1656
        return env->mgregs;
1657
    case PS_IG:
1658
        return env->igregs;
1659
    }
1660
}
1661

    
1662
static inline void change_pstate(uint64_t new_pstate)
1663
{
1664
    uint64_t pstate_regs, new_pstate_regs;
1665
    uint64_t *src, *dst;
1666

    
1667
    pstate_regs = env->pstate & 0xc01;
1668
    new_pstate_regs = new_pstate & 0xc01;
1669
    if (new_pstate_regs != pstate_regs) {
1670
        // Switch global register bank
1671
        src = get_gregset(new_pstate_regs);
1672
        dst = get_gregset(pstate_regs);
1673
        memcpy32(dst, env->gregs);
1674
        memcpy32(env->gregs, src);
1675
    }
1676
    env->pstate = new_pstate;
1677
}
1678

    
1679
void helper_wrpstate(target_ulong new_state)
1680
{
1681
    change_pstate(new_state & 0xf3f);
1682
}
1683

    
1684
void helper_done(void)
1685
{
1686
    env->tl--;
1687
    env->pc = env->tnpc[env->tl];
1688
    env->npc = env->tnpc[env->tl] + 4;
1689
    PUT_CCR(env, env->tstate[env->tl] >> 32);
1690
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1691
    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1692
    PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1693
}
1694

    
1695
void helper_retry(void)
1696
{
1697
    env->tl--;
1698
    env->pc = env->tpc[env->tl];
1699
    env->npc = env->tnpc[env->tl];
1700
    PUT_CCR(env, env->tstate[env->tl] >> 32);
1701
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1702
    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1703
    PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1704
}
1705
#endif
1706

    
1707
void set_cwp(int new_cwp)
1708
{
1709
    /* put the modified wrap registers at their proper location */
1710
    if (env->cwp == (NWINDOWS - 1))
1711
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1712
    env->cwp = new_cwp;
1713
    /* put the wrap registers at their temporary location */
1714
    if (new_cwp == (NWINDOWS - 1))
1715
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1716
    env->regwptr = env->regbase + (new_cwp * 16);
1717
    REGWPTR = env->regwptr;
1718
}
1719

    
1720
void cpu_set_cwp(CPUState *env1, int new_cwp)
1721
{
1722
    CPUState *saved_env;
1723
#ifdef reg_REGWPTR
1724
    target_ulong *saved_regwptr;
1725
#endif
1726

    
1727
    saved_env = env;
1728
#ifdef reg_REGWPTR
1729
    saved_regwptr = REGWPTR;
1730
#endif
1731
    env = env1;
1732
    set_cwp(new_cwp);
1733
    env = saved_env;
1734
#ifdef reg_REGWPTR
1735
    REGWPTR = saved_regwptr;
1736
#endif
1737
}
1738

    
1739
#ifdef TARGET_SPARC64
1740
#ifdef DEBUG_PCALL
1741
static const char * const excp_names[0x50] = {
1742
    [TT_TFAULT] = "Instruction Access Fault",
1743
    [TT_TMISS] = "Instruction Access MMU Miss",
1744
    [TT_CODE_ACCESS] = "Instruction Access Error",
1745
    [TT_ILL_INSN] = "Illegal Instruction",
1746
    [TT_PRIV_INSN] = "Privileged Instruction",
1747
    [TT_NFPU_INSN] = "FPU Disabled",
1748
    [TT_FP_EXCP] = "FPU Exception",
1749
    [TT_TOVF] = "Tag Overflow",
1750
    [TT_CLRWIN] = "Clean Windows",
1751
    [TT_DIV_ZERO] = "Division By Zero",
1752
    [TT_DFAULT] = "Data Access Fault",
1753
    [TT_DMISS] = "Data Access MMU Miss",
1754
    [TT_DATA_ACCESS] = "Data Access Error",
1755
    [TT_DPROT] = "Data Protection Error",
1756
    [TT_UNALIGNED] = "Unaligned Memory Access",
1757
    [TT_PRIV_ACT] = "Privileged Action",
1758
    [TT_EXTINT | 0x1] = "External Interrupt 1",
1759
    [TT_EXTINT | 0x2] = "External Interrupt 2",
1760
    [TT_EXTINT | 0x3] = "External Interrupt 3",
1761
    [TT_EXTINT | 0x4] = "External Interrupt 4",
1762
    [TT_EXTINT | 0x5] = "External Interrupt 5",
1763
    [TT_EXTINT | 0x6] = "External Interrupt 6",
1764
    [TT_EXTINT | 0x7] = "External Interrupt 7",
1765
    [TT_EXTINT | 0x8] = "External Interrupt 8",
1766
    [TT_EXTINT | 0x9] = "External Interrupt 9",
1767
    [TT_EXTINT | 0xa] = "External Interrupt 10",
1768
    [TT_EXTINT | 0xb] = "External Interrupt 11",
1769
    [TT_EXTINT | 0xc] = "External Interrupt 12",
1770
    [TT_EXTINT | 0xd] = "External Interrupt 13",
1771
    [TT_EXTINT | 0xe] = "External Interrupt 14",
1772
    [TT_EXTINT | 0xf] = "External Interrupt 15",
1773
};
1774
#endif
1775

    
1776
void do_interrupt(int intno)
1777
{
1778
#ifdef DEBUG_PCALL
1779
    if (loglevel & CPU_LOG_INT) {
1780
        static int count;
1781
        const char *name;
1782

    
1783
        if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
1784
            name = "Unknown";
1785
        else if (intno >= 0x100)
1786
            name = "Trap Instruction";
1787
        else if (intno >= 0xc0)
1788
            name = "Window Fill";
1789
        else if (intno >= 0x80)
1790
            name = "Window Spill";
1791
        else {
1792
            name = excp_names[intno];
1793
            if (!name)
1794
                name = "Unknown";
1795
        }
1796

    
1797
        fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
1798
                " SP=%016" PRIx64 "\n",
1799
                count, name, intno,
1800
                env->pc,
1801
                env->npc, env->regwptr[6]);
1802
        cpu_dump_state(env, logfile, fprintf, 0);
1803
#if 0
1804
        {
1805
            int i;
1806
            uint8_t *ptr;
1807

1808
            fprintf(logfile, "       code=");
1809
            ptr = (uint8_t *)env->pc;
1810
            for(i = 0; i < 16; i++) {
1811
                fprintf(logfile, " %02x", ldub(ptr + i));
1812
            }
1813
            fprintf(logfile, "\n");
1814
        }
1815
#endif
1816
        count++;
1817
    }
1818
#endif
1819
#if !defined(CONFIG_USER_ONLY)
1820
    if (env->tl == MAXTL) {
1821
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1822
        return;
1823
    }
1824
#endif
1825
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
1826
        ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
1827
    env->tpc[env->tl] = env->pc;
1828
    env->tnpc[env->tl] = env->npc;
1829
    env->tt[env->tl] = intno;
1830
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
1831

    
1832
    if (intno == TT_CLRWIN)
1833
        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1834
    else if ((intno & 0x1c0) == TT_SPILL)
1835
        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1836
    else if ((intno & 0x1c0) == TT_FILL)
1837
        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
1838
    env->tbr &= ~0x7fffULL;
1839
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1840
    if (env->tl < MAXTL - 1) {
1841
        env->tl++;
1842
    } else {
1843
        env->pstate |= PS_RED;
1844
        if (env->tl != MAXTL)
1845
            env->tl++;
1846
    }
1847
    env->pc = env->tbr;
1848
    env->npc = env->pc + 4;
1849
    env->exception_index = 0;
1850
}
1851
#else
1852
#ifdef DEBUG_PCALL
1853
static const char * const excp_names[0x80] = {
1854
    [TT_TFAULT] = "Instruction Access Fault",
1855
    [TT_ILL_INSN] = "Illegal Instruction",
1856
    [TT_PRIV_INSN] = "Privileged Instruction",
1857
    [TT_NFPU_INSN] = "FPU Disabled",
1858
    [TT_WIN_OVF] = "Window Overflow",
1859
    [TT_WIN_UNF] = "Window Underflow",
1860
    [TT_UNALIGNED] = "Unaligned Memory Access",
1861
    [TT_FP_EXCP] = "FPU Exception",
1862
    [TT_DFAULT] = "Data Access Fault",
1863
    [TT_TOVF] = "Tag Overflow",
1864
    [TT_EXTINT | 0x1] = "External Interrupt 1",
1865
    [TT_EXTINT | 0x2] = "External Interrupt 2",
1866
    [TT_EXTINT | 0x3] = "External Interrupt 3",
1867
    [TT_EXTINT | 0x4] = "External Interrupt 4",
1868
    [TT_EXTINT | 0x5] = "External Interrupt 5",
1869
    [TT_EXTINT | 0x6] = "External Interrupt 6",
1870
    [TT_EXTINT | 0x7] = "External Interrupt 7",
1871
    [TT_EXTINT | 0x8] = "External Interrupt 8",
1872
    [TT_EXTINT | 0x9] = "External Interrupt 9",
1873
    [TT_EXTINT | 0xa] = "External Interrupt 10",
1874
    [TT_EXTINT | 0xb] = "External Interrupt 11",
1875
    [TT_EXTINT | 0xc] = "External Interrupt 12",
1876
    [TT_EXTINT | 0xd] = "External Interrupt 13",
1877
    [TT_EXTINT | 0xe] = "External Interrupt 14",
1878
    [TT_EXTINT | 0xf] = "External Interrupt 15",
1879
    [TT_TOVF] = "Tag Overflow",
1880
    [TT_CODE_ACCESS] = "Instruction Access Error",
1881
    [TT_DATA_ACCESS] = "Data Access Error",
1882
    [TT_DIV_ZERO] = "Division By Zero",
1883
    [TT_NCP_INSN] = "Coprocessor Disabled",
1884
};
1885
#endif
1886

    
1887
void do_interrupt(int intno)
1888
{
1889
    int cwp;
1890

    
1891
#ifdef DEBUG_PCALL
1892
    if (loglevel & CPU_LOG_INT) {
1893
        static int count;
1894
        const char *name;
1895

    
1896
        if (intno < 0 || intno >= 0x100)
1897
            name = "Unknown";
1898
        else if (intno >= 0x80)
1899
            name = "Trap Instruction";
1900
        else {
1901
            name = excp_names[intno];
1902
            if (!name)
1903
                name = "Unknown";
1904
        }
1905

    
1906
        fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
1907
                count, name, intno,
1908
                env->pc,
1909
                env->npc, env->regwptr[6]);
1910
        cpu_dump_state(env, logfile, fprintf, 0);
1911
#if 0
1912
        {
1913
            int i;
1914
            uint8_t *ptr;
1915

1916
            fprintf(logfile, "       code=");
1917
            ptr = (uint8_t *)env->pc;
1918
            for(i = 0; i < 16; i++) {
1919
                fprintf(logfile, " %02x", ldub(ptr + i));
1920
            }
1921
            fprintf(logfile, "\n");
1922
        }
1923
#endif
1924
        count++;
1925
    }
1926
#endif
1927
#if !defined(CONFIG_USER_ONLY)
1928
    if (env->psret == 0) {
1929
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1930
        return;
1931
    }
1932
#endif
1933
    env->psret = 0;
1934
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
1935
    set_cwp(cwp);
1936
    env->regwptr[9] = env->pc;
1937
    env->regwptr[10] = env->npc;
1938
    env->psrps = env->psrs;
1939
    env->psrs = 1;
1940
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1941
    env->pc = env->tbr;
1942
    env->npc = env->pc + 4;
1943
    env->exception_index = 0;
1944
}
1945
#endif
1946

    
1947
#if !defined(CONFIG_USER_ONLY)
1948

    
1949
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1950
                                void *retaddr);
1951

    
1952
#define MMUSUFFIX _mmu
1953
#define ALIGNED_ONLY
1954
#ifdef __s390__
1955
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1956
#else
1957
# define GETPC() (__builtin_return_address(0))
1958
#endif
1959

    
1960
#define SHIFT 0
1961
#include "softmmu_template.h"
1962

    
1963
#define SHIFT 1
1964
#include "softmmu_template.h"
1965

    
1966
#define SHIFT 2
1967
#include "softmmu_template.h"
1968

    
1969
#define SHIFT 3
1970
#include "softmmu_template.h"
1971

    
1972
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1973
                                void *retaddr)
1974
{
1975
#ifdef DEBUG_UNALIGNED
1976
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1977
#endif
1978
    raise_exception(TT_UNALIGNED);
1979
}
1980

    
1981
/* try to fill the TLB and return an exception if error. If retaddr is
1982
   NULL, it means that the function was called in C code (i.e. not
1983
   from generated code or from helper.c) */
1984
/* XXX: fix it to restore all registers */
1985
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1986
{
1987
    TranslationBlock *tb;
1988
    int ret;
1989
    unsigned long pc;
1990
    CPUState *saved_env;
1991

    
1992
    /* XXX: hack to restore env in all cases, even if not called from
1993
       generated code */
1994
    saved_env = env;
1995
    env = cpu_single_env;
1996

    
1997
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1998
    if (ret) {
1999
        if (retaddr) {
2000
            /* now we have a real cpu fault */
2001
            pc = (unsigned long)retaddr;
2002
            tb = tb_find_pc(pc);
2003
            if (tb) {
2004
                /* the PC is inside the translated code. It means that we have
2005
                   a virtual CPU fault */
2006
                cpu_restore_state(tb, env, pc, (void *)T2);
2007
            }
2008
        }
2009
        cpu_loop_exit();
2010
    }
2011
    env = saved_env;
2012
}
2013

    
2014
#endif
2015

    
2016
#ifndef TARGET_SPARC64
2017
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2018
                          int is_asi)
2019
{
2020
    CPUState *saved_env;
2021

    
2022
    /* XXX: hack to restore env in all cases, even if not called from
2023
       generated code */
2024
    saved_env = env;
2025
    env = cpu_single_env;
2026
#ifdef DEBUG_UNASSIGNED
2027
    if (is_asi)
2028
        printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
2029
               TARGET_FMT_lx "\n",
2030
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
2031
               env->pc);
2032
    else
2033
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
2034
               TARGET_FMT_lx "\n",
2035
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
2036
#endif
2037
    if (env->mmuregs[3]) /* Fault status register */
2038
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
2039
    if (is_asi)
2040
        env->mmuregs[3] |= 1 << 16;
2041
    if (env->psrs)
2042
        env->mmuregs[3] |= 1 << 5;
2043
    if (is_exec)
2044
        env->mmuregs[3] |= 1 << 6;
2045
    if (is_write)
2046
        env->mmuregs[3] |= 1 << 7;
2047
    env->mmuregs[3] |= (5 << 2) | 2;
2048
    env->mmuregs[4] = addr; /* Fault address register */
2049
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
2050
        if (is_exec)
2051
            raise_exception(TT_CODE_ACCESS);
2052
        else
2053
            raise_exception(TT_DATA_ACCESS);
2054
    }
2055
    env = saved_env;
2056
}
2057
#else
2058
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
2059
                          int is_asi)
2060
{
2061
#ifdef DEBUG_UNASSIGNED
2062
    CPUState *saved_env;
2063

    
2064
    /* XXX: hack to restore env in all cases, even if not called from
2065
       generated code */
2066
    saved_env = env;
2067
    env = cpu_single_env;
2068
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
2069
           addr, env->pc);
2070
    env = saved_env;
2071
#endif
2072
    if (is_exec)
2073
        raise_exception(TT_CODE_ACCESS);
2074
    else
2075
        raise_exception(TT_DATA_ACCESS);
2076
}
2077
#endif
2078