Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (52.3 kB)

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

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

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

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

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

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

    
38
void check_ieee_exceptions()
39
{
40
     T0 = get_float_exception_flags(&env->fp_status);
41
     if (T0)
42
     {
43
        /* Copy IEEE 754 flags into FSR */
44
        if (T0 & float_flag_invalid)
45
            env->fsr |= FSR_NVC;
46
        if (T0 & float_flag_overflow)
47
            env->fsr |= FSR_OFC;
48
        if (T0 & float_flag_underflow)
49
            env->fsr |= FSR_UFC;
50
        if (T0 & float_flag_divbyzero)
51
            env->fsr |= FSR_DZC;
52
        if (T0 & float_flag_inexact)
53
            env->fsr |= FSR_NXC;
54

    
55
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
56
        {
57
            /* Unmasked exception, generate a trap */
58
            env->fsr |= FSR_FTT_IEEE_EXCP;
59
            raise_exception(TT_FP_EXCP);
60
        }
61
        else
62
        {
63
            /* Accumulate exceptions */
64
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
65
        }
66
     }
67
}
68

    
69
#ifdef USE_INT_TO_FLOAT_HELPERS
70
void do_fitos(void)
71
{
72
    set_float_exception_flags(0, &env->fp_status);
73
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
74
    check_ieee_exceptions();
75
}
76

    
77
void do_fitod(void)
78
{
79
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
80
}
81

    
82
#if defined(CONFIG_USER_ONLY)
83
void do_fitoq(void)
84
{
85
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
86
}
87
#endif
88

    
89
#ifdef TARGET_SPARC64
90
void do_fxtos(void)
91
{
92
    set_float_exception_flags(0, &env->fp_status);
93
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
94
    check_ieee_exceptions();
95
}
96

    
97
void do_fxtod(void)
98
{
99
    set_float_exception_flags(0, &env->fp_status);
100
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
101
    check_ieee_exceptions();
102
}
103

    
104
#if defined(CONFIG_USER_ONLY)
105
void do_fxtoq(void)
106
{
107
    set_float_exception_flags(0, &env->fp_status);
108
    QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status);
109
    check_ieee_exceptions();
110
}
111
#endif
112
#endif
113
#endif
114

    
115
void do_fabss(void)
116
{
117
    FT0 = float32_abs(FT1);
118
}
119

    
120
#ifdef TARGET_SPARC64
121
void do_fabsd(void)
122
{
123
    DT0 = float64_abs(DT1);
124
}
125

    
126
#if defined(CONFIG_USER_ONLY)
127
void do_fabsq(void)
128
{
129
    QT0 = float128_abs(QT1);
130
}
131
#endif
132
#endif
133

    
134
void do_fsqrts(void)
135
{
136
    set_float_exception_flags(0, &env->fp_status);
137
    FT0 = float32_sqrt(FT1, &env->fp_status);
138
    check_ieee_exceptions();
139
}
140

    
141
void do_fsqrtd(void)
142
{
143
    set_float_exception_flags(0, &env->fp_status);
144
    DT0 = float64_sqrt(DT1, &env->fp_status);
145
    check_ieee_exceptions();
146
}
147

    
148
#if defined(CONFIG_USER_ONLY)
149
void do_fsqrtq(void)
150
{
151
    set_float_exception_flags(0, &env->fp_status);
152
    QT0 = float128_sqrt(QT1, &env->fp_status);
153
    check_ieee_exceptions();
154
}
155
#endif
156

    
157
#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
158
    void glue(do_, name) (void)                                         \
159
    {                                                                   \
160
        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
161
        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
162
        case float_relation_unordered:                                  \
163
            T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
164
            if ((env->fsr & FSR_NVM) || TRAP) {                         \
165
                env->fsr |= T0;                                         \
166
                env->fsr |= FSR_NVC;                                    \
167
                env->fsr |= FSR_FTT_IEEE_EXCP;                          \
168
                raise_exception(TT_FP_EXCP);                            \
169
            } else {                                                    \
170
                env->fsr |= FSR_NVA;                                    \
171
            }                                                           \
172
            break;                                                      \
173
        case float_relation_less:                                       \
174
            T0 = FSR_FCC0 << FS;                                        \
175
            break;                                                      \
176
        case float_relation_greater:                                    \
177
            T0 = FSR_FCC1 << FS;                                        \
178
            break;                                                      \
179
        default:                                                        \
180
            T0 = 0;                                                     \
181
            break;                                                      \
182
        }                                                               \
183
        env->fsr |= T0;                                                 \
184
    }
185

    
186
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
187
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
188

    
189
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
190
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
191

    
192
#ifdef CONFIG_USER_ONLY
193
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
194
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
195
#endif
196

    
197
#ifdef TARGET_SPARC64
198
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
199
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
200

    
201
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
202
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
203

    
204
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
205
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
206

    
207
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
208
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
209

    
210
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
211
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
212

    
213
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
214
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
215
#ifdef CONFIG_USER_ONLY
216
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
217
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
218
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
219
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
220
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
221
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
222
#endif
223
#endif
224

    
225
#ifndef TARGET_SPARC64
226
#ifndef CONFIG_USER_ONLY
227

    
228
#ifdef DEBUG_MXCC
229
static void dump_mxcc(CPUState *env)
230
{
231
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
232
        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
233
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
234
           "          %016llx %016llx %016llx %016llx\n",
235
        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
236
        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
237
}
238
#endif
239

    
240
#ifdef DEBUG_ASI
241
static void dump_asi(const char * txt, uint32_t addr, int asi, int size,
242
                     uint32_t r1, uint32_t r2)
243
{
244
    switch (size)
245
    {
246
    case 1:
247
        DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff);
248
        break;
249
    case 2:
250
        DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff);
251
        break;
252
    case 4:
253
        DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1);
254
        break;
255
    case 8:
256
        DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi,
257
                    r2 | ((uint64_t)r1 << 32));
258
        break;
259
    }
260
}
261
#endif
262

    
263
void helper_ld_asi(int asi, int size, int sign)
264
{
265
    uint32_t ret = 0;
266
    uint64_t tmp;
267
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
268
    uint32_t last_T0 = T0;
269
#endif
270

    
271
    switch (asi) {
272
    case 2: /* SuperSparc MXCC registers */
273
        switch (T0) {
274
        case 0x01c00a00: /* MXCC control register */
275
            if (size == 8) {
276
                ret = env->mxccregs[3] >> 32;
277
                T0 = env->mxccregs[3];
278
            } else
279
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
280
            break;
281
        case 0x01c00a04: /* MXCC control register */
282
            if (size == 4)
283
                ret = env->mxccregs[3];
284
            else
285
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
286
            break;
287
        case 0x01c00c00: /* Module reset register */
288
            if (size == 8) {
289
                ret = env->mxccregs[5] >> 32;
290
                T0 = env->mxccregs[5];
291
                // should we do something here?
292
            } else
293
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
294
            break;
295
        case 0x01c00f00: /* MBus port address register */
296
            if (size == 8) {
297
                ret = env->mxccregs[7] >> 32;
298
                T0 = env->mxccregs[7];
299
            } else
300
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
301
            break;
302
        default:
303
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
304
            break;
305
        }
306
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
307
                     "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
308
#ifdef DEBUG_MXCC
309
        dump_mxcc(env);
310
#endif
311
        break;
312
    case 3: /* MMU probe */
313
        {
314
            int mmulev;
315

    
316
            mmulev = (T0 >> 8) & 15;
317
            if (mmulev > 4)
318
                ret = 0;
319
            else {
320
                ret = mmu_probe(env, T0, mmulev);
321
                //bswap32s(&ret);
322
            }
323
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
324
        }
325
        break;
326
    case 4: /* read MMU regs */
327
        {
328
            int reg = (T0 >> 8) & 0x1f;
329

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

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

    
559
            mmulev = (T0 >> 8) & 15;
560
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
561
            switch (mmulev) {
562
            case 0: // flush page
563
                tlb_flush_page(env, T0 & 0xfffff000);
564
                break;
565
            case 1: // flush segment (256k)
566
            case 2: // flush region (16M)
567
            case 3: // flush context (4G)
568
            case 4: // flush entire
569
                tlb_flush(env, 1);
570
                break;
571
            default:
572
                break;
573
            }
574
#ifdef DEBUG_MMU
575
            dump_mmu(env);
576
#endif
577
        }
578
        break;
579
    case 4: /* write MMU regs */
580
        {
581
            int reg = (T0 >> 8) & 0x1f;
582
            uint32_t oldreg;
583

    
584
            oldreg = env->mmuregs[reg];
585
            switch(reg) {
586
            case 0:
587
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
588
                                    (T1 & 0x00ffffff);
589
                // Mappings generated during no-fault mode or MMU
590
                // disabled mode are invalid in normal mode
591
                if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
592
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
593
                    tlb_flush(env, 1);
594
                break;
595
            case 2:
596
                env->mmuregs[reg] = T1;
597
                if (oldreg != env->mmuregs[reg]) {
598
                    /* we flush when the MMU context changes because
599
                       QEMU has no MMU context support */
600
                    tlb_flush(env, 1);
601
                }
602
                break;
603
            case 3:
604
            case 4:
605
                break;
606
            case 0x13:
607
                env->mmuregs[3] = T1;
608
                break;
609
            case 0x14:
610
                env->mmuregs[4] = T1;
611
                break;
612
            default:
613
                env->mmuregs[reg] = T1;
614
                break;
615
            }
616
            if (oldreg != env->mmuregs[reg]) {
617
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
618
            }
619
#ifdef DEBUG_MMU
620
            dump_mmu(env);
621
#endif
622
        }
623
        break;
624
    case 0xa: /* User data access */
625
        switch(size) {
626
        case 1:
627
            stb_user(T0, T1);
628
            break;
629
        case 2:
630
            stw_user(T0 & ~1, T1);
631
            break;
632
        default:
633
        case 4:
634
            stl_user(T0 & ~3, T1);
635
            break;
636
        case 8:
637
            stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
638
            break;
639
        }
640
        break;
641
    case 0xb: /* Supervisor data access */
642
        switch(size) {
643
        case 1:
644
            stb_kernel(T0, T1);
645
            break;
646
        case 2:
647
            stw_kernel(T0 & ~1, T1);
648
            break;
649
        default:
650
        case 4:
651
            stl_kernel(T0 & ~3, T1);
652
            break;
653
        case 8:
654
            stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
655
            break;
656
        }
657
        break;
658
    case 0xc: /* I-cache tag */
659
    case 0xd: /* I-cache data */
660
    case 0xe: /* D-cache tag */
661
    case 0xf: /* D-cache data */
662
    case 0x10: /* I/D-cache flush page */
663
    case 0x11: /* I/D-cache flush segment */
664
    case 0x12: /* I/D-cache flush region */
665
    case 0x13: /* I/D-cache flush context */
666
    case 0x14: /* I/D-cache flush user */
667
        break;
668
    case 0x17: /* Block copy, sta access */
669
        {
670
            // value (T1) = src
671
            // address (T0) = dst
672
            // copy 32 bytes
673
            unsigned int i;
674
            uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
675

    
676
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
677
                temp = ldl_kernel(src);
678
                stl_kernel(dst, temp);
679
            }
680
        }
681
        break;
682
    case 0x1f: /* Block fill, stda access */
683
        {
684
            // value (T1, T2)
685
            // address (T0) = dst
686
            // fill 32 bytes
687
            unsigned int i;
688
            uint32_t dst = T0 & 7;
689
            uint64_t val;
690

    
691
            val = (((uint64_t)T1) << 32) | T2;
692

    
693
            for (i = 0; i < 32; i += 8, dst += 8)
694
                stq_kernel(dst, val);
695
        }
696
        break;
697
    case 0x20: /* MMU passthrough */
698
        {
699
            switch(size) {
700
            case 1:
701
                stb_phys(T0, T1);
702
                break;
703
            case 2:
704
                stw_phys(T0 & ~1, T1);
705
                break;
706
            case 4:
707
            default:
708
                stl_phys(T0 & ~3, T1);
709
                break;
710
            case 8:
711
                stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
712
                break;
713
            }
714
        }
715
        break;
716
    case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
717
    case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
718
        {
719
            switch(size) {
720
            case 1:
721
                stb_phys((target_phys_addr_t)T0
722
                         | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
723
                break;
724
            case 2:
725
                stw_phys((target_phys_addr_t)(T0 & ~1)
726
                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
727
                break;
728
            case 4:
729
            default:
730
                stl_phys((target_phys_addr_t)(T0 & ~3)
731
                           | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
732
                break;
733
            case 8:
734
                stq_phys((target_phys_addr_t)(T0 & ~7)
735
                           | ((target_phys_addr_t)(asi & 0xf) << 32),
736
                         ((uint64_t)T1 << 32) | T2);
737
                break;
738
            }
739
        }
740
        break;
741
    case 0x30: /* store buffer tags */
742
    case 0x31: /* store buffer data or Ross RT620 I-cache flush */
743
    case 0x32: /* store buffer control */
744
    case 0x36: /* I-cache flash clear */
745
    case 0x37: /* D-cache flash clear */
746
    case 0x38: /* breakpoint diagnostics */
747
    case 0x4c: /* breakpoint action */
748
        break;
749
    case 9: /* Supervisor code access, XXX */
750
    case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
751
    default:
752
        do_unassigned_access(T0, 1, 0, asi);
753
        break;
754
    }
755
#ifdef DEBUG_ASI
756
    dump_asi("write", T0, asi, size, T1, T2);
757
#endif
758
}
759

    
760
#endif /* CONFIG_USER_ONLY */
761
#else /* TARGET_SPARC64 */
762

    
763
#ifdef CONFIG_USER_ONLY
764
void helper_ld_asi(int asi, int size, int sign)
765
{
766
    uint64_t ret = 0;
767

    
768
    if (asi < 0x80)
769
        raise_exception(TT_PRIV_ACT);
770

    
771
    switch (asi) {
772
    case 0x80: // Primary
773
    case 0x82: // Primary no-fault
774
    case 0x88: // Primary LE
775
    case 0x8a: // Primary no-fault LE
776
        {
777
            switch(size) {
778
            case 1:
779
                ret = ldub_raw(T0);
780
                break;
781
            case 2:
782
                ret = lduw_raw(T0 & ~1);
783
                break;
784
            case 4:
785
                ret = ldl_raw(T0 & ~3);
786
                break;
787
            default:
788
            case 8:
789
                ret = ldq_raw(T0 & ~7);
790
                break;
791
            }
792
        }
793
        break;
794
    case 0x81: // Secondary
795
    case 0x83: // Secondary no-fault
796
    case 0x89: // Secondary LE
797
    case 0x8b: // Secondary no-fault LE
798
        // XXX
799
        break;
800
    default:
801
        break;
802
    }
803

    
804
    /* Convert from little endian */
805
    switch (asi) {
806
    case 0x88: // Primary LE
807
    case 0x89: // Secondary LE
808
    case 0x8a: // Primary no-fault LE
809
    case 0x8b: // Secondary no-fault LE
810
        switch(size) {
811
        case 2:
812
            ret = bswap16(ret);
813
            break;
814
        case 4:
815
            ret = bswap32(ret);
816
            break;
817
        case 8:
818
            ret = bswap64(ret);
819
            break;
820
        default:
821
            break;
822
        }
823
    default:
824
        break;
825
    }
826

    
827
    /* Convert to signed number */
828
    if (sign) {
829
        switch(size) {
830
        case 1:
831
            ret = (int8_t) ret;
832
            break;
833
        case 2:
834
            ret = (int16_t) ret;
835
            break;
836
        case 4:
837
            ret = (int32_t) ret;
838
            break;
839
        default:
840
            break;
841
        }
842
    }
843
    T1 = ret;
844
}
845

    
846
void helper_st_asi(int asi, int size)
847
{
848
    if (asi < 0x80)
849
        raise_exception(TT_PRIV_ACT);
850

    
851
    /* Convert to little endian */
852
    switch (asi) {
853
    case 0x88: // Primary LE
854
    case 0x89: // Secondary LE
855
        switch(size) {
856
        case 2:
857
            T0 = bswap16(T0);
858
            break;
859
        case 4:
860
            T0 = bswap32(T0);
861
            break;
862
        case 8:
863
            T0 = bswap64(T0);
864
            break;
865
        default:
866
            break;
867
        }
868
    default:
869
        break;
870
    }
871

    
872
    switch(asi) {
873
    case 0x80: // Primary
874
    case 0x88: // Primary LE
875
        {
876
            switch(size) {
877
            case 1:
878
                stb_raw(T0, T1);
879
                break;
880
            case 2:
881
                stw_raw(T0 & ~1, T1);
882
                break;
883
            case 4:
884
                stl_raw(T0 & ~3, T1);
885
                break;
886
            case 8:
887
            default:
888
                stq_raw(T0 & ~7, T1);
889
                break;
890
            }
891
        }
892
        break;
893
    case 0x81: // Secondary
894
    case 0x89: // Secondary LE
895
        // XXX
896
        return;
897

    
898
    case 0x82: // Primary no-fault, RO
899
    case 0x83: // Secondary no-fault, RO
900
    case 0x8a: // Primary no-fault LE, RO
901
    case 0x8b: // Secondary no-fault LE, RO
902
    default:
903
        do_unassigned_access(T0, 1, 0, 1);
904
        return;
905
    }
906
}
907

    
908
#else /* CONFIG_USER_ONLY */
909

    
910
void helper_ld_asi(int asi, int size, int sign)
911
{
912
    uint64_t ret = 0;
913

    
914
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
915
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
916
        raise_exception(TT_PRIV_ACT);
917

    
918
    switch (asi) {
919
    case 0x10: // As if user primary
920
    case 0x18: // As if user primary LE
921
    case 0x80: // Primary
922
    case 0x82: // Primary no-fault
923
    case 0x88: // Primary LE
924
    case 0x8a: // Primary no-fault LE
925
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
926
            if (env->hpstate & HS_PRIV) {
927
                switch(size) {
928
                case 1:
929
                    ret = ldub_hypv(T0);
930
                    break;
931
                case 2:
932
                    ret = lduw_hypv(T0 & ~1);
933
                    break;
934
                case 4:
935
                    ret = ldl_hypv(T0 & ~3);
936
                    break;
937
                default:
938
                case 8:
939
                    ret = ldq_hypv(T0 & ~7);
940
                    break;
941
                }
942
            } else {
943
                switch(size) {
944
                case 1:
945
                    ret = ldub_kernel(T0);
946
                    break;
947
                case 2:
948
                    ret = lduw_kernel(T0 & ~1);
949
                    break;
950
                case 4:
951
                    ret = ldl_kernel(T0 & ~3);
952
                    break;
953
                default:
954
                case 8:
955
                    ret = ldq_kernel(T0 & ~7);
956
                    break;
957
                }
958
            }
959
        } else {
960
            switch(size) {
961
            case 1:
962
                ret = ldub_user(T0);
963
                break;
964
            case 2:
965
                ret = lduw_user(T0 & ~1);
966
                break;
967
            case 4:
968
                ret = ldl_user(T0 & ~3);
969
                break;
970
            default:
971
            case 8:
972
                ret = ldq_user(T0 & ~7);
973
                break;
974
            }
975
        }
976
        break;
977
    case 0x14: // Bypass
978
    case 0x15: // Bypass, non-cacheable
979
    case 0x1c: // Bypass LE
980
    case 0x1d: // Bypass, non-cacheable LE
981
        {
982
            switch(size) {
983
            case 1:
984
                ret = ldub_phys(T0);
985
                break;
986
            case 2:
987
                ret = lduw_phys(T0 & ~1);
988
                break;
989
            case 4:
990
                ret = ldl_phys(T0 & ~3);
991
                break;
992
            default:
993
            case 8:
994
                ret = ldq_phys(T0 & ~7);
995
                break;
996
            }
997
            break;
998
        }
999
    case 0x04: // Nucleus
1000
    case 0x0c: // Nucleus Little Endian (LE)
1001
    case 0x11: // As if user secondary
1002
    case 0x19: // As if user secondary LE
1003
    case 0x24: // Nucleus quad LDD 128 bit atomic
1004
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1005
    case 0x4a: // UPA config
1006
    case 0x81: // Secondary
1007
    case 0x83: // Secondary no-fault
1008
    case 0x89: // Secondary LE
1009
    case 0x8b: // Secondary no-fault LE
1010
        // XXX
1011
        break;
1012
    case 0x45: // LSU
1013
        ret = env->lsu;
1014
        break;
1015
    case 0x50: // I-MMU regs
1016
        {
1017
            int reg = (T0 >> 3) & 0xf;
1018

    
1019
            ret = env->immuregs[reg];
1020
            break;
1021
        }
1022
    case 0x51: // I-MMU 8k TSB pointer
1023
    case 0x52: // I-MMU 64k TSB pointer
1024
    case 0x55: // I-MMU data access
1025
        // XXX
1026
        break;
1027
    case 0x56: // I-MMU tag read
1028
        {
1029
            unsigned int i;
1030

    
1031
            for (i = 0; i < 64; i++) {
1032
                // Valid, ctx match, vaddr match
1033
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1034
                    env->itlb_tag[i] == T0) {
1035
                    ret = env->itlb_tag[i];
1036
                    break;
1037
                }
1038
            }
1039
            break;
1040
        }
1041
    case 0x58: // D-MMU regs
1042
        {
1043
            int reg = (T0 >> 3) & 0xf;
1044

    
1045
            ret = env->dmmuregs[reg];
1046
            break;
1047
        }
1048
    case 0x5e: // D-MMU tag read
1049
        {
1050
            unsigned int i;
1051

    
1052
            for (i = 0; i < 64; i++) {
1053
                // Valid, ctx match, vaddr match
1054
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1055
                    env->dtlb_tag[i] == T0) {
1056
                    ret = env->dtlb_tag[i];
1057
                    break;
1058
                }
1059
            }
1060
            break;
1061
        }
1062
    case 0x59: // D-MMU 8k TSB pointer
1063
    case 0x5a: // D-MMU 64k TSB pointer
1064
    case 0x5b: // D-MMU data pointer
1065
    case 0x5d: // D-MMU data access
1066
    case 0x48: // Interrupt dispatch, RO
1067
    case 0x49: // Interrupt data receive
1068
    case 0x7f: // Incoming interrupt vector, RO
1069
        // XXX
1070
        break;
1071
    case 0x54: // I-MMU data in, WO
1072
    case 0x57: // I-MMU demap, WO
1073
    case 0x5c: // D-MMU data in, WO
1074
    case 0x5f: // D-MMU demap, WO
1075
    case 0x77: // Interrupt vector, WO
1076
    default:
1077
        do_unassigned_access(T0, 0, 0, 1);
1078
        ret = 0;
1079
        break;
1080
    }
1081

    
1082
    /* Convert from little endian */
1083
    switch (asi) {
1084
    case 0x0c: // Nucleus Little Endian (LE)
1085
    case 0x18: // As if user primary LE
1086
    case 0x19: // As if user secondary LE
1087
    case 0x1c: // Bypass LE
1088
    case 0x1d: // Bypass, non-cacheable LE
1089
    case 0x88: // Primary LE
1090
    case 0x89: // Secondary LE
1091
    case 0x8a: // Primary no-fault LE
1092
    case 0x8b: // Secondary no-fault LE
1093
        switch(size) {
1094
        case 2:
1095
            ret = bswap16(ret);
1096
            break;
1097
        case 4:
1098
            ret = bswap32(ret);
1099
            break;
1100
        case 8:
1101
            ret = bswap64(ret);
1102
            break;
1103
        default:
1104
            break;
1105
        }
1106
    default:
1107
        break;
1108
    }
1109

    
1110
    /* Convert to signed number */
1111
    if (sign) {
1112
        switch(size) {
1113
        case 1:
1114
            ret = (int8_t) ret;
1115
            break;
1116
        case 2:
1117
            ret = (int16_t) ret;
1118
            break;
1119
        case 4:
1120
            ret = (int32_t) ret;
1121
            break;
1122
        default:
1123
            break;
1124
        }
1125
    }
1126
    T1 = ret;
1127
}
1128

    
1129
void helper_st_asi(int asi, int size)
1130
{
1131
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1132
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1133
        raise_exception(TT_PRIV_ACT);
1134

    
1135
    /* Convert to little endian */
1136
    switch (asi) {
1137
    case 0x0c: // Nucleus Little Endian (LE)
1138
    case 0x18: // As if user primary LE
1139
    case 0x19: // As if user secondary LE
1140
    case 0x1c: // Bypass LE
1141
    case 0x1d: // Bypass, non-cacheable LE
1142
    case 0x88: // Primary LE
1143
    case 0x89: // Secondary LE
1144
        switch(size) {
1145
        case 2:
1146
            T0 = bswap16(T0);
1147
            break;
1148
        case 4:
1149
            T0 = bswap32(T0);
1150
            break;
1151
        case 8:
1152
            T0 = bswap64(T0);
1153
            break;
1154
        default:
1155
            break;
1156
        }
1157
    default:
1158
        break;
1159
    }
1160

    
1161
    switch(asi) {
1162
    case 0x10: // As if user primary
1163
    case 0x18: // As if user primary LE
1164
    case 0x80: // Primary
1165
    case 0x88: // Primary LE
1166
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1167
            if (env->hpstate & HS_PRIV) {
1168
                switch(size) {
1169
                case 1:
1170
                    stb_hypv(T0, T1);
1171
                    break;
1172
                case 2:
1173
                    stw_hypv(T0 & ~1, T1);
1174
                    break;
1175
                case 4:
1176
                    stl_hypv(T0 & ~3, T1);
1177
                    break;
1178
                case 8:
1179
                default:
1180
                    stq_hypv(T0 & ~7, T1);
1181
                    break;
1182
                }
1183
            } else {
1184
                switch(size) {
1185
                case 1:
1186
                    stb_kernel(T0, T1);
1187
                    break;
1188
                case 2:
1189
                    stw_kernel(T0 & ~1, T1);
1190
                    break;
1191
                case 4:
1192
                    stl_kernel(T0 & ~3, T1);
1193
                    break;
1194
                case 8:
1195
                default:
1196
                    stq_kernel(T0 & ~7, T1);
1197
                    break;
1198
                }
1199
            }
1200
        } else {
1201
            switch(size) {
1202
            case 1:
1203
                stb_user(T0, T1);
1204
                break;
1205
            case 2:
1206
                stw_user(T0 & ~1, T1);
1207
                break;
1208
            case 4:
1209
                stl_user(T0 & ~3, T1);
1210
                break;
1211
            case 8:
1212
            default:
1213
                stq_user(T0 & ~7, T1);
1214
                break;
1215
            }
1216
        }
1217
        break;
1218
    case 0x14: // Bypass
1219
    case 0x15: // Bypass, non-cacheable
1220
    case 0x1c: // Bypass LE
1221
    case 0x1d: // Bypass, non-cacheable LE
1222
        {
1223
            switch(size) {
1224
            case 1:
1225
                stb_phys(T0, T1);
1226
                break;
1227
            case 2:
1228
                stw_phys(T0 & ~1, T1);
1229
                break;
1230
            case 4:
1231
                stl_phys(T0 & ~3, T1);
1232
                break;
1233
            case 8:
1234
            default:
1235
                stq_phys(T0 & ~7, T1);
1236
                break;
1237
            }
1238
        }
1239
        return;
1240
    case 0x04: // Nucleus
1241
    case 0x0c: // Nucleus Little Endian (LE)
1242
    case 0x11: // As if user secondary
1243
    case 0x19: // As if user secondary LE
1244
    case 0x24: // Nucleus quad LDD 128 bit atomic
1245
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1246
    case 0x4a: // UPA config
1247
    case 0x81: // Secondary
1248
    case 0x89: // Secondary LE
1249
        // XXX
1250
        return;
1251
    case 0x45: // LSU
1252
        {
1253
            uint64_t oldreg;
1254

    
1255
            oldreg = env->lsu;
1256
            env->lsu = T1 & (DMMU_E | IMMU_E);
1257
            // Mappings generated during D/I MMU disabled mode are
1258
            // invalid in normal mode
1259
            if (oldreg != env->lsu) {
1260
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1261
#ifdef DEBUG_MMU
1262
                dump_mmu(env);
1263
#endif
1264
                tlb_flush(env, 1);
1265
            }
1266
            return;
1267
        }
1268
    case 0x50: // I-MMU regs
1269
        {
1270
            int reg = (T0 >> 3) & 0xf;
1271
            uint64_t oldreg;
1272

    
1273
            oldreg = env->immuregs[reg];
1274
            switch(reg) {
1275
            case 0: // RO
1276
            case 4:
1277
                return;
1278
            case 1: // Not in I-MMU
1279
            case 2:
1280
            case 7:
1281
            case 8:
1282
                return;
1283
            case 3: // SFSR
1284
                if ((T1 & 1) == 0)
1285
                    T1 = 0; // Clear SFSR
1286
                break;
1287
            case 5: // TSB access
1288
            case 6: // Tag access
1289
            default:
1290
                break;
1291
            }
1292
            env->immuregs[reg] = T1;
1293
            if (oldreg != env->immuregs[reg]) {
1294
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1295
            }
1296
#ifdef DEBUG_MMU
1297
            dump_mmu(env);
1298
#endif
1299
            return;
1300
        }
1301
    case 0x54: // I-MMU data in
1302
        {
1303
            unsigned int i;
1304

    
1305
            // Try finding an invalid entry
1306
            for (i = 0; i < 64; i++) {
1307
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1308
                    env->itlb_tag[i] = env->immuregs[6];
1309
                    env->itlb_tte[i] = T1;
1310
                    return;
1311
                }
1312
            }
1313
            // Try finding an unlocked entry
1314
            for (i = 0; i < 64; i++) {
1315
                if ((env->itlb_tte[i] & 0x40) == 0) {
1316
                    env->itlb_tag[i] = env->immuregs[6];
1317
                    env->itlb_tte[i] = T1;
1318
                    return;
1319
                }
1320
            }
1321
            // error state?
1322
            return;
1323
        }
1324
    case 0x55: // I-MMU data access
1325
        {
1326
            unsigned int i = (T0 >> 3) & 0x3f;
1327

    
1328
            env->itlb_tag[i] = env->immuregs[6];
1329
            env->itlb_tte[i] = T1;
1330
            return;
1331
        }
1332
    case 0x57: // I-MMU demap
1333
        // XXX
1334
        return;
1335
    case 0x58: // D-MMU regs
1336
        {
1337
            int reg = (T0 >> 3) & 0xf;
1338
            uint64_t oldreg;
1339

    
1340
            oldreg = env->dmmuregs[reg];
1341
            switch(reg) {
1342
            case 0: // RO
1343
            case 4:
1344
                return;
1345
            case 3: // SFSR
1346
                if ((T1 & 1) == 0) {
1347
                    T1 = 0; // Clear SFSR, Fault address
1348
                    env->dmmuregs[4] = 0;
1349
                }
1350
                env->dmmuregs[reg] = T1;
1351
                break;
1352
            case 1: // Primary context
1353
            case 2: // Secondary context
1354
            case 5: // TSB access
1355
            case 6: // Tag access
1356
            case 7: // Virtual Watchpoint
1357
            case 8: // Physical Watchpoint
1358
            default:
1359
                break;
1360
            }
1361
            env->dmmuregs[reg] = T1;
1362
            if (oldreg != env->dmmuregs[reg]) {
1363
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1364
            }
1365
#ifdef DEBUG_MMU
1366
            dump_mmu(env);
1367
#endif
1368
            return;
1369
        }
1370
    case 0x5c: // D-MMU data in
1371
        {
1372
            unsigned int i;
1373

    
1374
            // Try finding an invalid entry
1375
            for (i = 0; i < 64; i++) {
1376
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
1377
                    env->dtlb_tag[i] = env->dmmuregs[6];
1378
                    env->dtlb_tte[i] = T1;
1379
                    return;
1380
                }
1381
            }
1382
            // Try finding an unlocked entry
1383
            for (i = 0; i < 64; i++) {
1384
                if ((env->dtlb_tte[i] & 0x40) == 0) {
1385
                    env->dtlb_tag[i] = env->dmmuregs[6];
1386
                    env->dtlb_tte[i] = T1;
1387
                    return;
1388
                }
1389
            }
1390
            // error state?
1391
            return;
1392
        }
1393
    case 0x5d: // D-MMU data access
1394
        {
1395
            unsigned int i = (T0 >> 3) & 0x3f;
1396

    
1397
            env->dtlb_tag[i] = env->dmmuregs[6];
1398
            env->dtlb_tte[i] = T1;
1399
            return;
1400
        }
1401
    case 0x5f: // D-MMU demap
1402
    case 0x49: // Interrupt data receive
1403
        // XXX
1404
        return;
1405
    case 0x51: // I-MMU 8k TSB pointer, RO
1406
    case 0x52: // I-MMU 64k TSB pointer, RO
1407
    case 0x56: // I-MMU tag read, RO
1408
    case 0x59: // D-MMU 8k TSB pointer, RO
1409
    case 0x5a: // D-MMU 64k TSB pointer, RO
1410
    case 0x5b: // D-MMU data pointer, RO
1411
    case 0x5e: // D-MMU tag read, RO
1412
    case 0x48: // Interrupt dispatch, RO
1413
    case 0x7f: // Incoming interrupt vector, RO
1414
    case 0x82: // Primary no-fault, RO
1415
    case 0x83: // Secondary no-fault, RO
1416
    case 0x8a: // Primary no-fault LE, RO
1417
    case 0x8b: // Secondary no-fault LE, RO
1418
    default:
1419
        do_unassigned_access(T0, 1, 0, 1);
1420
        return;
1421
    }
1422
}
1423
#endif /* CONFIG_USER_ONLY */
1424

    
1425
void helper_ldf_asi(int asi, int size, int rd)
1426
{
1427
    target_ulong tmp_T0 = T0, tmp_T1 = T1;
1428
    unsigned int i;
1429

    
1430
    switch (asi) {
1431
    case 0xf0: // Block load primary
1432
    case 0xf1: // Block load secondary
1433
    case 0xf8: // Block load primary LE
1434
    case 0xf9: // Block load secondary LE
1435
        if (rd & 7) {
1436
            raise_exception(TT_ILL_INSN);
1437
            return;
1438
        }
1439
        if (T0 & 0x3f) {
1440
            raise_exception(TT_UNALIGNED);
1441
            return;
1442
        }
1443
        for (i = 0; i < 16; i++) {
1444
            helper_ld_asi(asi & 0x8f, 4, 0);
1445
            *(uint32_t *)&env->fpr[rd++] = T1;
1446
            T0 += 4;
1447
        }
1448
        T0 = tmp_T0;
1449
        T1 = tmp_T1;
1450

    
1451
        return;
1452
    default:
1453
        break;
1454
    }
1455

    
1456
    helper_ld_asi(asi, size, 0);
1457
    switch(size) {
1458
    default:
1459
    case 4:
1460
        *((uint32_t *)&FT0) = T1;
1461
        break;
1462
    case 8:
1463
        *((int64_t *)&DT0) = T1;
1464
        break;
1465
#if defined(CONFIG_USER_ONLY)
1466
    case 16:
1467
        // XXX
1468
        break;
1469
#endif
1470
    }
1471
    T1 = tmp_T1;
1472
}
1473

    
1474
void helper_stf_asi(int asi, int size, int rd)
1475
{
1476
    target_ulong tmp_T0 = T0, tmp_T1 = T1;
1477
    unsigned int i;
1478

    
1479
    switch (asi) {
1480
    case 0xf0: // Block store primary
1481
    case 0xf1: // Block store secondary
1482
    case 0xf8: // Block store primary LE
1483
    case 0xf9: // Block store secondary LE
1484
        if (rd & 7) {
1485
            raise_exception(TT_ILL_INSN);
1486
            return;
1487
        }
1488
        if (T0 & 0x3f) {
1489
            raise_exception(TT_UNALIGNED);
1490
            return;
1491
        }
1492
        for (i = 0; i < 16; i++) {
1493
            T1 = *(uint32_t *)&env->fpr[rd++];
1494
            helper_st_asi(asi & 0x8f, 4);
1495
            T0 += 4;
1496
        }
1497
        T0 = tmp_T0;
1498
        T1 = tmp_T1;
1499

    
1500
        return;
1501
    default:
1502
        break;
1503
    }
1504

    
1505
    switch(size) {
1506
    default:
1507
    case 4:
1508
        T1 = *((uint32_t *)&FT0);
1509
        break;
1510
    case 8:
1511
        T1 = *((int64_t *)&DT0);
1512
        break;
1513
#if defined(CONFIG_USER_ONLY)
1514
    case 16:
1515
        // XXX
1516
        break;
1517
#endif
1518
    }
1519
    helper_st_asi(asi, size);
1520
    T1 = tmp_T1;
1521
}
1522

    
1523
#endif /* TARGET_SPARC64 */
1524

    
1525
#ifndef TARGET_SPARC64
1526
void helper_rett()
1527
{
1528
    unsigned int cwp;
1529

    
1530
    if (env->psret == 1)
1531
        raise_exception(TT_ILL_INSN);
1532

    
1533
    env->psret = 1;
1534
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
1535
    if (env->wim & (1 << cwp)) {
1536
        raise_exception(TT_WIN_UNF);
1537
    }
1538
    set_cwp(cwp);
1539
    env->psrs = env->psrps;
1540
}
1541
#endif
1542

    
1543
void helper_ldfsr(void)
1544
{
1545
    int rnd_mode;
1546
    switch (env->fsr & FSR_RD_MASK) {
1547
    case FSR_RD_NEAREST:
1548
        rnd_mode = float_round_nearest_even;
1549
        break;
1550
    default:
1551
    case FSR_RD_ZERO:
1552
        rnd_mode = float_round_to_zero;
1553
        break;
1554
    case FSR_RD_POS:
1555
        rnd_mode = float_round_up;
1556
        break;
1557
    case FSR_RD_NEG:
1558
        rnd_mode = float_round_down;
1559
        break;
1560
    }
1561
    set_float_rounding_mode(rnd_mode, &env->fp_status);
1562
}
1563

    
1564
void helper_debug()
1565
{
1566
    env->exception_index = EXCP_DEBUG;
1567
    cpu_loop_exit();
1568
}
1569

    
1570
#ifndef TARGET_SPARC64
1571
void do_wrpsr()
1572
{
1573
    if ((T0 & PSR_CWP) >= NWINDOWS)
1574
        raise_exception(TT_ILL_INSN);
1575
    else
1576
        PUT_PSR(env, T0);
1577
}
1578

    
1579
void do_rdpsr()
1580
{
1581
    T0 = GET_PSR(env);
1582
}
1583

    
1584
#else
1585

    
1586
void do_popc()
1587
{
1588
    T0 = ctpop64(T1);
1589
}
1590

    
1591
static inline uint64_t *get_gregset(uint64_t pstate)
1592
{
1593
    switch (pstate) {
1594
    default:
1595
    case 0:
1596
        return env->bgregs;
1597
    case PS_AG:
1598
        return env->agregs;
1599
    case PS_MG:
1600
        return env->mgregs;
1601
    case PS_IG:
1602
        return env->igregs;
1603
    }
1604
}
1605

    
1606
static inline void change_pstate(uint64_t new_pstate)
1607
{
1608
    uint64_t pstate_regs, new_pstate_regs;
1609
    uint64_t *src, *dst;
1610

    
1611
    pstate_regs = env->pstate & 0xc01;
1612
    new_pstate_regs = new_pstate & 0xc01;
1613
    if (new_pstate_regs != pstate_regs) {
1614
        // Switch global register bank
1615
        src = get_gregset(new_pstate_regs);
1616
        dst = get_gregset(pstate_regs);
1617
        memcpy32(dst, env->gregs);
1618
        memcpy32(env->gregs, src);
1619
    }
1620
    env->pstate = new_pstate;
1621
}
1622

    
1623
void do_wrpstate(void)
1624
{
1625
    change_pstate(T0 & 0xf3f);
1626
}
1627

    
1628
void do_done(void)
1629
{
1630
    env->tl--;
1631
    env->pc = env->tnpc[env->tl];
1632
    env->npc = env->tnpc[env->tl] + 4;
1633
    PUT_CCR(env, env->tstate[env->tl] >> 32);
1634
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1635
    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1636
    PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1637
}
1638

    
1639
void do_retry(void)
1640
{
1641
    env->tl--;
1642
    env->pc = env->tpc[env->tl];
1643
    env->npc = env->tnpc[env->tl];
1644
    PUT_CCR(env, env->tstate[env->tl] >> 32);
1645
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1646
    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1647
    PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1648
}
1649
#endif
1650

    
1651
void set_cwp(int new_cwp)
1652
{
1653
    /* put the modified wrap registers at their proper location */
1654
    if (env->cwp == (NWINDOWS - 1))
1655
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1656
    env->cwp = new_cwp;
1657
    /* put the wrap registers at their temporary location */
1658
    if (new_cwp == (NWINDOWS - 1))
1659
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1660
    env->regwptr = env->regbase + (new_cwp * 16);
1661
    REGWPTR = env->regwptr;
1662
}
1663

    
1664
void cpu_set_cwp(CPUState *env1, int new_cwp)
1665
{
1666
    CPUState *saved_env;
1667
#ifdef reg_REGWPTR
1668
    target_ulong *saved_regwptr;
1669
#endif
1670

    
1671
    saved_env = env;
1672
#ifdef reg_REGWPTR
1673
    saved_regwptr = REGWPTR;
1674
#endif
1675
    env = env1;
1676
    set_cwp(new_cwp);
1677
    env = saved_env;
1678
#ifdef reg_REGWPTR
1679
    REGWPTR = saved_regwptr;
1680
#endif
1681
}
1682

    
1683
#ifdef TARGET_SPARC64
1684
void do_interrupt(int intno)
1685
{
1686
#ifdef DEBUG_PCALL
1687
    if (loglevel & CPU_LOG_INT) {
1688
        static int count;
1689
        fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
1690
                count, intno,
1691
                env->pc,
1692
                env->npc, env->regwptr[6]);
1693
        cpu_dump_state(env, logfile, fprintf, 0);
1694
#if 0
1695
        {
1696
            int i;
1697
            uint8_t *ptr;
1698

1699
            fprintf(logfile, "       code=");
1700
            ptr = (uint8_t *)env->pc;
1701
            for(i = 0; i < 16; i++) {
1702
                fprintf(logfile, " %02x", ldub(ptr + i));
1703
            }
1704
            fprintf(logfile, "\n");
1705
        }
1706
#endif
1707
        count++;
1708
    }
1709
#endif
1710
#if !defined(CONFIG_USER_ONLY)
1711
    if (env->tl == MAXTL) {
1712
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1713
        return;
1714
    }
1715
#endif
1716
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
1717
        ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
1718
    env->tpc[env->tl] = env->pc;
1719
    env->tnpc[env->tl] = env->npc;
1720
    env->tt[env->tl] = intno;
1721
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
1722

    
1723
    if (intno == TT_CLRWIN)
1724
        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1725
    else if ((intno & 0x1c0) == TT_SPILL)
1726
        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1727
    else if ((intno & 0x1c0) == TT_FILL)
1728
        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
1729
    env->tbr &= ~0x7fffULL;
1730
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1731
    if (env->tl < MAXTL - 1) {
1732
        env->tl++;
1733
    } else {
1734
        env->pstate |= PS_RED;
1735
        if (env->tl != MAXTL)
1736
            env->tl++;
1737
    }
1738
    env->pc = env->tbr;
1739
    env->npc = env->pc + 4;
1740
    env->exception_index = 0;
1741
}
1742
#else
1743
void do_interrupt(int intno)
1744
{
1745
    int cwp;
1746

    
1747
#ifdef DEBUG_PCALL
1748
    if (loglevel & CPU_LOG_INT) {
1749
        static int count;
1750
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
1751
                count, intno,
1752
                env->pc,
1753
                env->npc, env->regwptr[6]);
1754
        cpu_dump_state(env, logfile, fprintf, 0);
1755
#if 0
1756
        {
1757
            int i;
1758
            uint8_t *ptr;
1759

1760
            fprintf(logfile, "       code=");
1761
            ptr = (uint8_t *)env->pc;
1762
            for(i = 0; i < 16; i++) {
1763
                fprintf(logfile, " %02x", ldub(ptr + i));
1764
            }
1765
            fprintf(logfile, "\n");
1766
        }
1767
#endif
1768
        count++;
1769
    }
1770
#endif
1771
#if !defined(CONFIG_USER_ONLY)
1772
    if (env->psret == 0) {
1773
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1774
        return;
1775
    }
1776
#endif
1777
    env->psret = 0;
1778
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
1779
    set_cwp(cwp);
1780
    env->regwptr[9] = env->pc;
1781
    env->regwptr[10] = env->npc;
1782
    env->psrps = env->psrs;
1783
    env->psrs = 1;
1784
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1785
    env->pc = env->tbr;
1786
    env->npc = env->pc + 4;
1787
    env->exception_index = 0;
1788
}
1789
#endif
1790

    
1791
#if !defined(CONFIG_USER_ONLY)
1792

    
1793
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1794
                                void *retaddr);
1795

    
1796
#define MMUSUFFIX _mmu
1797
#define ALIGNED_ONLY
1798
#ifdef __s390__
1799
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1800
#else
1801
# define GETPC() (__builtin_return_address(0))
1802
#endif
1803

    
1804
#define SHIFT 0
1805
#include "softmmu_template.h"
1806

    
1807
#define SHIFT 1
1808
#include "softmmu_template.h"
1809

    
1810
#define SHIFT 2
1811
#include "softmmu_template.h"
1812

    
1813
#define SHIFT 3
1814
#include "softmmu_template.h"
1815

    
1816
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1817
                                void *retaddr)
1818
{
1819
#ifdef DEBUG_UNALIGNED
1820
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1821
#endif
1822
    raise_exception(TT_UNALIGNED);
1823
}
1824

    
1825
/* try to fill the TLB and return an exception if error. If retaddr is
1826
   NULL, it means that the function was called in C code (i.e. not
1827
   from generated code or from helper.c) */
1828
/* XXX: fix it to restore all registers */
1829
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1830
{
1831
    TranslationBlock *tb;
1832
    int ret;
1833
    unsigned long pc;
1834
    CPUState *saved_env;
1835

    
1836
    /* XXX: hack to restore env in all cases, even if not called from
1837
       generated code */
1838
    saved_env = env;
1839
    env = cpu_single_env;
1840

    
1841
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1842
    if (ret) {
1843
        if (retaddr) {
1844
            /* now we have a real cpu fault */
1845
            pc = (unsigned long)retaddr;
1846
            tb = tb_find_pc(pc);
1847
            if (tb) {
1848
                /* the PC is inside the translated code. It means that we have
1849
                   a virtual CPU fault */
1850
                cpu_restore_state(tb, env, pc, (void *)T2);
1851
            }
1852
        }
1853
        cpu_loop_exit();
1854
    }
1855
    env = saved_env;
1856
}
1857

    
1858
#endif
1859

    
1860
#ifndef TARGET_SPARC64
1861
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1862
                          int is_asi)
1863
{
1864
    CPUState *saved_env;
1865

    
1866
    /* XXX: hack to restore env in all cases, even if not called from
1867
       generated code */
1868
    saved_env = env;
1869
    env = cpu_single_env;
1870
#ifdef DEBUG_UNASSIGNED
1871
    if (is_asi)
1872
        printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
1873
               TARGET_FMT_lx "\n",
1874
               is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
1875
               env->pc);
1876
    else
1877
        printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
1878
               TARGET_FMT_lx "\n",
1879
               is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
1880
#endif
1881
    if (env->mmuregs[3]) /* Fault status register */
1882
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
1883
    if (is_asi)
1884
        env->mmuregs[3] |= 1 << 16;
1885
    if (env->psrs)
1886
        env->mmuregs[3] |= 1 << 5;
1887
    if (is_exec)
1888
        env->mmuregs[3] |= 1 << 6;
1889
    if (is_write)
1890
        env->mmuregs[3] |= 1 << 7;
1891
    env->mmuregs[3] |= (5 << 2) | 2;
1892
    env->mmuregs[4] = addr; /* Fault address register */
1893
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1894
        if (is_exec)
1895
            raise_exception(TT_CODE_ACCESS);
1896
        else
1897
            raise_exception(TT_DATA_ACCESS);
1898
    }
1899
    env = saved_env;
1900
}
1901
#else
1902
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1903
                          int is_asi)
1904
{
1905
#ifdef DEBUG_UNASSIGNED
1906
    CPUState *saved_env;
1907

    
1908
    /* XXX: hack to restore env in all cases, even if not called from
1909
       generated code */
1910
    saved_env = env;
1911
    env = cpu_single_env;
1912
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
1913
           addr, env->pc);
1914
    env = saved_env;
1915
#endif
1916
    if (is_exec)
1917
        raise_exception(TT_CODE_ACCESS);
1918
    else
1919
        raise_exception(TT_DATA_ACCESS);
1920
}
1921
#endif
1922