Statistics
| Branch: | Revision:

root / target-sparc / op_helper.c @ 666c87aa

History | View | Annotate | Download (51.1 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

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

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

    
24
void raise_exception(int tt)
25
{
26
    env->exception_index = tt;
27
    cpu_loop_exit();
28
}
29

    
30
void check_ieee_exceptions()
31
{
32
     T0 = get_float_exception_flags(&env->fp_status);
33
     if (T0)
34
     {
35
        /* Copy IEEE 754 flags into FSR */
36
        if (T0 & float_flag_invalid)
37
            env->fsr |= FSR_NVC;
38
        if (T0 & float_flag_overflow)
39
            env->fsr |= FSR_OFC;
40
        if (T0 & float_flag_underflow)
41
            env->fsr |= FSR_UFC;
42
        if (T0 & float_flag_divbyzero)
43
            env->fsr |= FSR_DZC;
44
        if (T0 & float_flag_inexact)
45
            env->fsr |= FSR_NXC;
46

    
47
        if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
48
        {
49
            /* Unmasked exception, generate a trap */
50
            env->fsr |= FSR_FTT_IEEE_EXCP;
51
            raise_exception(TT_FP_EXCP);
52
        }
53
        else
54
        {
55
            /* Accumulate exceptions */
56
            env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
57
        }
58
     }
59
}
60

    
61
#ifdef USE_INT_TO_FLOAT_HELPERS
62
void do_fitos(void)
63
{
64
    set_float_exception_flags(0, &env->fp_status);
65
    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
66
    check_ieee_exceptions();
67
}
68

    
69
void do_fitod(void)
70
{
71
    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
72
}
73

    
74
#if defined(CONFIG_USER_ONLY)
75
void do_fitoq(void)
76
{
77
    QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
78
}
79
#endif
80

    
81
#ifdef TARGET_SPARC64
82
void do_fxtos(void)
83
{
84
    set_float_exception_flags(0, &env->fp_status);
85
    FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
86
    check_ieee_exceptions();
87
}
88

    
89
void do_fxtod(void)
90
{
91
    set_float_exception_flags(0, &env->fp_status);
92
    DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
93
    check_ieee_exceptions();
94
}
95

    
96
#if defined(CONFIG_USER_ONLY)
97
void do_fxtoq(void)
98
{
99
    set_float_exception_flags(0, &env->fp_status);
100
    QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status);
101
    check_ieee_exceptions();
102
}
103
#endif
104
#endif
105
#endif
106

    
107
void do_fabss(void)
108
{
109
    FT0 = float32_abs(FT1);
110
}
111

    
112
#ifdef TARGET_SPARC64
113
void do_fabsd(void)
114
{
115
    DT0 = float64_abs(DT1);
116
}
117

    
118
#if defined(CONFIG_USER_ONLY)
119
void do_fabsq(void)
120
{
121
    QT0 = float128_abs(QT1);
122
}
123
#endif
124
#endif
125

    
126
void do_fsqrts(void)
127
{
128
    set_float_exception_flags(0, &env->fp_status);
129
    FT0 = float32_sqrt(FT1, &env->fp_status);
130
    check_ieee_exceptions();
131
}
132

    
133
void do_fsqrtd(void)
134
{
135
    set_float_exception_flags(0, &env->fp_status);
136
    DT0 = float64_sqrt(DT1, &env->fp_status);
137
    check_ieee_exceptions();
138
}
139

    
140
#if defined(CONFIG_USER_ONLY)
141
void do_fsqrtq(void)
142
{
143
    set_float_exception_flags(0, &env->fp_status);
144
    QT0 = float128_sqrt(QT1, &env->fp_status);
145
    check_ieee_exceptions();
146
}
147
#endif
148

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

    
178
GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
179
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
180

    
181
GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
182
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
183

    
184
#ifdef CONFIG_USER_ONLY
185
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
186
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
187
#endif
188

    
189
#ifdef TARGET_SPARC64
190
GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
191
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
192

    
193
GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
194
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
195

    
196
GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
197
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
198

    
199
GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
200
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
201

    
202
GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
203
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
204

    
205
GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
206
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
207
#ifdef CONFIG_USER_ONLY
208
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
209
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
210
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
211
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
212
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
213
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
214
#endif
215
#endif
216

    
217
#ifndef TARGET_SPARC64
218
#ifndef CONFIG_USER_ONLY
219

    
220
#ifdef DEBUG_MXCC
221
static void dump_mxcc(CPUState *env)
222
{
223
    printf("mxccdata: %016llx %016llx %016llx %016llx\n",
224
        env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
225
    printf("mxccregs: %016llx %016llx %016llx %016llx\n"
226
           "          %016llx %016llx %016llx %016llx\n",
227
        env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
228
        env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
229
}
230
#endif
231

    
232
void helper_ld_asi(int asi, int size, int sign)
233
{
234
    uint32_t ret = 0;
235
    uint64_t tmp;
236
#ifdef DEBUG_MXCC
237
    uint32_t last_T0 = T0;
238
#endif
239

    
240
    switch (asi) {
241
    case 2: /* SuperSparc MXCC registers */
242
        switch (T0) {
243
        case 0x01c00a00: /* MXCC control register */
244
            if (size == 8) {
245
                ret = env->mxccregs[3] >> 32;
246
                T0 = env->mxccregs[3];
247
            } else
248
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
249
            break;
250
        case 0x01c00a04: /* MXCC control register */
251
            if (size == 4)
252
                ret = env->mxccregs[3];
253
            else
254
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
255
            break;
256
        case 0x01c00c00: /* Module reset register */
257
            if (size == 8) {
258
                ret = env->mxccregs[5] >> 32;
259
                T0 = env->mxccregs[5];
260
                // should we do something here?
261
            } else
262
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
263
            break;
264
        case 0x01c00f00: /* MBus port address register */
265
            if (size == 8) {
266
                ret = env->mxccregs[7] >> 32;
267
                T0 = env->mxccregs[7];
268
            } else
269
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
270
            break;
271
        default:
272
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
273
            break;
274
        }
275
        DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
276
                     "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
277
#ifdef DEBUG_MXCC
278
        dump_mxcc(env);
279
#endif
280
        break;
281
    case 3: /* MMU probe */
282
        {
283
            int mmulev;
284

    
285
            mmulev = (T0 >> 8) & 15;
286
            if (mmulev > 4)
287
                ret = 0;
288
            else {
289
                ret = mmu_probe(env, T0, mmulev);
290
                //bswap32s(&ret);
291
            }
292
            DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
293
        }
294
        break;
295
    case 4: /* read MMU regs */
296
        {
297
            int reg = (T0 >> 8) & 0x1f;
298

    
299
            ret = env->mmuregs[reg];
300
            if (reg == 3) /* Fault status cleared on read */
301
                env->mmuregs[3] = 0;
302
            else if (reg == 0x13) /* Fault status read */
303
                ret = env->mmuregs[3];
304
            else if (reg == 0x14) /* Fault address read */
305
                ret = env->mmuregs[4];
306
            DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
307
        }
308
        break;
309
    case 9: /* Supervisor code access */
310
        switch(size) {
311
        case 1:
312
            ret = ldub_code(T0);
313
            break;
314
        case 2:
315
            ret = lduw_code(T0 & ~1);
316
            break;
317
        default:
318
        case 4:
319
            ret = ldl_code(T0 & ~3);
320
            break;
321
        case 8:
322
            tmp = ldq_code(T0 & ~7);
323
            ret = tmp >> 32;
324
            T0 = tmp;
325
            break;
326
        }
327
        break;
328
    case 0xa: /* User data access */
329
        switch(size) {
330
        case 1:
331
            ret = ldub_user(T0);
332
            break;
333
        case 2:
334
            ret = lduw_user(T0 & ~1);
335
            break;
336
        default:
337
        case 4:
338
            ret = ldl_user(T0 & ~3);
339
            break;
340
        case 8:
341
            tmp = ldq_user(T0 & ~7);
342
            ret = tmp >> 32;
343
            T0 = tmp;
344
            break;
345
        }
346
        break;
347
    case 0xb: /* Supervisor data access */
348
        switch(size) {
349
        case 1:
350
            ret = ldub_kernel(T0);
351
            break;
352
        case 2:
353
            ret = lduw_kernel(T0 & ~1);
354
            break;
355
        default:
356
        case 4:
357
            ret = ldl_kernel(T0 & ~3);
358
            break;
359
        case 8:
360
            tmp = ldq_kernel(T0 & ~7);
361
            ret = tmp >> 32;
362
            T0 = tmp;
363
            break;
364
        }
365
        break;
366
    case 0xc: /* I-cache tag */
367
    case 0xd: /* I-cache data */
368
    case 0xe: /* D-cache tag */
369
    case 0xf: /* D-cache data */
370
        break;
371
    case 0x20: /* MMU passthrough */
372
        switch(size) {
373
        case 1:
374
            ret = ldub_phys(T0);
375
            break;
376
        case 2:
377
            ret = lduw_phys(T0 & ~1);
378
            break;
379
        default:
380
        case 4:
381
            ret = ldl_phys(T0 & ~3);
382
            break;
383
        case 8:
384
            tmp = ldq_phys(T0 & ~7);
385
            ret = tmp >> 32;
386
            T0 = tmp;
387
            break;
388
        }
389
        break;
390
    case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
391
    case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
392
        switch(size) {
393
        case 1:
394
            ret = ldub_phys((target_phys_addr_t)T0
395
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
396
            break;
397
        case 2:
398
            ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
399
                            | ((target_phys_addr_t)(asi & 0xf) << 32));
400
            break;
401
        default:
402
        case 4:
403
            ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
404
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
405
            break;
406
        case 8:
407
            tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
408
                           | ((target_phys_addr_t)(asi & 0xf) << 32));
409
            ret = tmp >> 32;
410
            T0 = tmp;
411
            break;
412
        }
413
        break;
414
    case 0x39: /* data cache diagnostic register */
415
        ret = 0;
416
        break;
417
    case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
418
    default:
419
        do_unassigned_access(T0, 0, 0, 1);
420
        ret = 0;
421
        break;
422
    }
423
    if (sign) {
424
        switch(size) {
425
        case 1:
426
            T1 = (int8_t) ret;
427
            break;
428
        case 2:
429
            T1 = (int16_t) ret;
430
            break;
431
        default:
432
            T1 = ret;
433
            break;
434
        }
435
    }
436
    else
437
        T1 = ret;
438
}
439

    
440
void helper_st_asi(int asi, int size)
441
{
442
    switch(asi) {
443
    case 2: /* SuperSparc MXCC registers */
444
        switch (T0) {
445
        case 0x01c00000: /* MXCC stream data register 0 */
446
            if (size == 8)
447
                env->mxccdata[0] = ((uint64_t)T1 << 32) | T2;
448
            else
449
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
450
            break;
451
        case 0x01c00008: /* MXCC stream data register 1 */
452
            if (size == 8)
453
                env->mxccdata[1] = ((uint64_t)T1 << 32) | T2;
454
            else
455
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
456
            break;
457
        case 0x01c00010: /* MXCC stream data register 2 */
458
            if (size == 8)
459
                env->mxccdata[2] = ((uint64_t)T1 << 32) | T2;
460
            else
461
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
462
            break;
463
        case 0x01c00018: /* MXCC stream data register 3 */
464
            if (size == 8)
465
                env->mxccdata[3] = ((uint64_t)T1 << 32) | T2;
466
            else
467
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
468
            break;
469
        case 0x01c00100: /* MXCC stream source */
470
            if (size == 8)
471
                env->mxccregs[0] = ((uint64_t)T1 << 32) | T2;
472
            else
473
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
474
            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
475
            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
476
            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
477
            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
478
            break;
479
        case 0x01c00200: /* MXCC stream destination */
480
            if (size == 8)
481
                env->mxccregs[1] = ((uint64_t)T1 << 32) | T2;
482
            else
483
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
484
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
485
            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
486
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
487
            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
488
            break;
489
        case 0x01c00a00: /* MXCC control register */
490
            if (size == 8)
491
                env->mxccregs[3] = ((uint64_t)T1 << 32) | T2;
492
            else
493
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
494
            break;
495
        case 0x01c00a04: /* MXCC control register */
496
            if (size == 4)
497
                env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1;
498
            else
499
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
500
            break;
501
        case 0x01c00e00: /* MXCC error register  */
502
            // writing a 1 bit clears the error
503
            if (size == 8)
504
                env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2);
505
            else
506
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
507
            break;
508
        case 0x01c00f00: /* MBus port address register */
509
            if (size == 8)
510
                env->mxccregs[7] = ((uint64_t)T1 << 32) | T2;
511
            else
512
                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
513
            break;
514
        default:
515
            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
516
            break;
517
        }
518
        DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
519
#ifdef DEBUG_MXCC
520
        dump_mxcc(env);
521
#endif
522
        break;
523
    case 3: /* MMU flush */
524
        {
525
            int mmulev;
526

    
527
            mmulev = (T0 >> 8) & 15;
528
            DPRINTF_MMU("mmu flush level %d\n", mmulev);
529
            switch (mmulev) {
530
            case 0: // flush page
531
                tlb_flush_page(env, T0 & 0xfffff000);
532
                break;
533
            case 1: // flush segment (256k)
534
            case 2: // flush region (16M)
535
            case 3: // flush context (4G)
536
            case 4: // flush entire
537
                tlb_flush(env, 1);
538
                break;
539
            default:
540
                break;
541
            }
542
#ifdef DEBUG_MMU
543
            dump_mmu(env);
544
#endif
545
            return;
546
        }
547
    case 4: /* write MMU regs */
548
        {
549
            int reg = (T0 >> 8) & 0x1f;
550
            uint32_t oldreg;
551

    
552
            oldreg = env->mmuregs[reg];
553
            switch(reg) {
554
            case 0:
555
                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
556
                                    (T1 & 0x00ffffff);
557
                // Mappings generated during no-fault mode or MMU
558
                // disabled mode are invalid in normal mode
559
                if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
560
                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
561
                    tlb_flush(env, 1);
562
                break;
563
            case 2:
564
                env->mmuregs[reg] = T1;
565
                if (oldreg != env->mmuregs[reg]) {
566
                    /* we flush when the MMU context changes because
567
                       QEMU has no MMU context support */
568
                    tlb_flush(env, 1);
569
                }
570
                break;
571
            case 3:
572
            case 4:
573
                break;
574
            case 0x13:
575
                env->mmuregs[3] = T1;
576
                break;
577
            case 0x14:
578
                env->mmuregs[4] = T1;
579
                break;
580
            default:
581
                env->mmuregs[reg] = T1;
582
                break;
583
            }
584
            if (oldreg != env->mmuregs[reg]) {
585
                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
586
            }
587
#ifdef DEBUG_MMU
588
            dump_mmu(env);
589
#endif
590
            return;
591
        }
592
    case 0xa: /* User data access */
593
        switch(size) {
594
        case 1:
595
            stb_user(T0, T1);
596
            break;
597
        case 2:
598
            stw_user(T0 & ~1, T1);
599
            break;
600
        default:
601
        case 4:
602
            stl_user(T0 & ~3, T1);
603
            break;
604
        case 8:
605
            stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
606
            break;
607
        }
608
        break;
609
    case 0xb: /* Supervisor data access */
610
        switch(size) {
611
        case 1:
612
            stb_kernel(T0, T1);
613
            break;
614
        case 2:
615
            stw_kernel(T0 & ~1, T1);
616
            break;
617
        default:
618
        case 4:
619
            stl_kernel(T0 & ~3, T1);
620
            break;
621
        case 8:
622
            stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
623
            break;
624
        }
625
        break;
626
    case 0xc: /* I-cache tag */
627
    case 0xd: /* I-cache data */
628
    case 0xe: /* D-cache tag */
629
    case 0xf: /* D-cache data */
630
    case 0x10: /* I/D-cache flush page */
631
    case 0x11: /* I/D-cache flush segment */
632
    case 0x12: /* I/D-cache flush region */
633
    case 0x13: /* I/D-cache flush context */
634
    case 0x14: /* I/D-cache flush user */
635
        break;
636
    case 0x17: /* Block copy, sta access */
637
        {
638
            // value (T1) = src
639
            // address (T0) = dst
640
            // copy 32 bytes
641
            unsigned int i;
642
            uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
643

    
644
            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
645
                temp = ldl_kernel(src);
646
                stl_kernel(dst, temp);
647
            }
648
        }
649
        return;
650
    case 0x1f: /* Block fill, stda access */
651
        {
652
            // value (T1, T2)
653
            // address (T0) = dst
654
            // fill 32 bytes
655
            unsigned int i;
656
            uint32_t dst = T0 & 7;
657
            uint64_t val;
658

    
659
            val = (((uint64_t)T1) << 32) | T2;
660

    
661
            for (i = 0; i < 32; i += 8, dst += 8)
662
                stq_kernel(dst, val);
663
        }
664
        return;
665
    case 0x20: /* MMU passthrough */
666
        {
667
            switch(size) {
668
            case 1:
669
                stb_phys(T0, T1);
670
                break;
671
            case 2:
672
                stw_phys(T0 & ~1, T1);
673
                break;
674
            case 4:
675
            default:
676
                stl_phys(T0 & ~3, T1);
677
                break;
678
            case 8:
679
                stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
680
                break;
681
            }
682
        }
683
        return;
684
    case 0x2e: /* MMU passthrough, 0xexxxxxxxx */
685
    case 0x2f: /* MMU passthrough, 0xfxxxxxxxx */
686
        {
687
            switch(size) {
688
            case 1:
689
                stb_phys((target_phys_addr_t)T0
690
                         | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
691
                break;
692
            case 2:
693
                stw_phys((target_phys_addr_t)(T0 & ~1)
694
                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
695
                break;
696
            case 4:
697
            default:
698
                stl_phys((target_phys_addr_t)(T0 & ~3)
699
                           | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
700
                break;
701
            case 8:
702
                stq_phys((target_phys_addr_t)(T0 & ~7)
703
                           | ((target_phys_addr_t)(asi & 0xf) << 32),
704
                         ((uint64_t)T1 << 32) | T2);
705
                break;
706
            }
707
        }
708
        return;
709
    case 0x30: /* store buffer tags */
710
    case 0x31: /* store buffer data or Ross RT620 I-cache flush */
711
    case 0x32: /* store buffer control */
712
    case 0x36: /* I-cache flash clear */
713
    case 0x37: /* D-cache flash clear */
714
    case 0x38: /* breakpoint diagnostics */
715
    case 0x4c: /* breakpoint action */
716
        break;
717
    case 9: /* Supervisor code access, XXX */
718
    case 0x21 ... 0x2d: /* MMU passthrough, unassigned */
719
    default:
720
        do_unassigned_access(T0, 1, 0, 1);
721
        return;
722
    }
723
}
724

    
725
#endif /* CONFIG_USER_ONLY */
726
#else /* TARGET_SPARC64 */
727

    
728
#ifdef CONFIG_USER_ONLY
729
void helper_ld_asi(int asi, int size, int sign)
730
{
731
    uint64_t ret = 0;
732

    
733
    if (asi < 0x80)
734
        raise_exception(TT_PRIV_ACT);
735

    
736
    switch (asi) {
737
    case 0x80: // Primary
738
    case 0x82: // Primary no-fault
739
    case 0x88: // Primary LE
740
    case 0x8a: // Primary no-fault LE
741
        {
742
            switch(size) {
743
            case 1:
744
                ret = ldub_raw(T0);
745
                break;
746
            case 2:
747
                ret = lduw_raw(T0 & ~1);
748
                break;
749
            case 4:
750
                ret = ldl_raw(T0 & ~3);
751
                break;
752
            default:
753
            case 8:
754
                ret = ldq_raw(T0 & ~7);
755
                break;
756
            }
757
        }
758
        break;
759
    case 0x81: // Secondary
760
    case 0x83: // Secondary no-fault
761
    case 0x89: // Secondary LE
762
    case 0x8b: // Secondary no-fault LE
763
        // XXX
764
        break;
765
    default:
766
        break;
767
    }
768

    
769
    /* Convert from little endian */
770
    switch (asi) {
771
    case 0x88: // Primary LE
772
    case 0x89: // Secondary LE
773
    case 0x8a: // Primary no-fault LE
774
    case 0x8b: // Secondary no-fault LE
775
        switch(size) {
776
        case 2:
777
            ret = bswap16(ret);
778
            break;
779
        case 4:
780
            ret = bswap32(ret);
781
            break;
782
        case 8:
783
            ret = bswap64(ret);
784
            break;
785
        default:
786
            break;
787
        }
788
    default:
789
        break;
790
    }
791

    
792
    /* Convert to signed number */
793
    if (sign) {
794
        switch(size) {
795
        case 1:
796
            ret = (int8_t) ret;
797
            break;
798
        case 2:
799
            ret = (int16_t) ret;
800
            break;
801
        case 4:
802
            ret = (int32_t) ret;
803
            break;
804
        default:
805
            break;
806
        }
807
    }
808
    T1 = ret;
809
}
810

    
811
void helper_st_asi(int asi, int size)
812
{
813
    if (asi < 0x80)
814
        raise_exception(TT_PRIV_ACT);
815

    
816
    /* Convert to little endian */
817
    switch (asi) {
818
    case 0x88: // Primary LE
819
    case 0x89: // Secondary LE
820
        switch(size) {
821
        case 2:
822
            T0 = bswap16(T0);
823
            break;
824
        case 4:
825
            T0 = bswap32(T0);
826
            break;
827
        case 8:
828
            T0 = bswap64(T0);
829
            break;
830
        default:
831
            break;
832
        }
833
    default:
834
        break;
835
    }
836

    
837
    switch(asi) {
838
    case 0x80: // Primary
839
    case 0x88: // Primary LE
840
        {
841
            switch(size) {
842
            case 1:
843
                stb_raw(T0, T1);
844
                break;
845
            case 2:
846
                stw_raw(T0 & ~1, T1);
847
                break;
848
            case 4:
849
                stl_raw(T0 & ~3, T1);
850
                break;
851
            case 8:
852
            default:
853
                stq_raw(T0 & ~7, T1);
854
                break;
855
            }
856
        }
857
        break;
858
    case 0x81: // Secondary
859
    case 0x89: // Secondary LE
860
        // XXX
861
        return;
862

    
863
    case 0x82: // Primary no-fault, RO
864
    case 0x83: // Secondary no-fault, RO
865
    case 0x8a: // Primary no-fault LE, RO
866
    case 0x8b: // Secondary no-fault LE, RO
867
    default:
868
        do_unassigned_access(T0, 1, 0, 1);
869
        return;
870
    }
871
}
872

    
873
#else /* CONFIG_USER_ONLY */
874

    
875
void helper_ld_asi(int asi, int size, int sign)
876
{
877
    uint64_t ret = 0;
878

    
879
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
880
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
881
        raise_exception(TT_PRIV_ACT);
882

    
883
    switch (asi) {
884
    case 0x10: // As if user primary
885
    case 0x18: // As if user primary LE
886
    case 0x80: // Primary
887
    case 0x82: // Primary no-fault
888
    case 0x88: // Primary LE
889
    case 0x8a: // Primary no-fault LE
890
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
891
            if (env->hpstate & HS_PRIV) {
892
                switch(size) {
893
                case 1:
894
                    ret = ldub_hypv(T0);
895
                    break;
896
                case 2:
897
                    ret = lduw_hypv(T0 & ~1);
898
                    break;
899
                case 4:
900
                    ret = ldl_hypv(T0 & ~3);
901
                    break;
902
                default:
903
                case 8:
904
                    ret = ldq_hypv(T0 & ~7);
905
                    break;
906
                }
907
            } else {
908
                switch(size) {
909
                case 1:
910
                    ret = ldub_kernel(T0);
911
                    break;
912
                case 2:
913
                    ret = lduw_kernel(T0 & ~1);
914
                    break;
915
                case 4:
916
                    ret = ldl_kernel(T0 & ~3);
917
                    break;
918
                default:
919
                case 8:
920
                    ret = ldq_kernel(T0 & ~7);
921
                    break;
922
                }
923
            }
924
        } else {
925
            switch(size) {
926
            case 1:
927
                ret = ldub_user(T0);
928
                break;
929
            case 2:
930
                ret = lduw_user(T0 & ~1);
931
                break;
932
            case 4:
933
                ret = ldl_user(T0 & ~3);
934
                break;
935
            default:
936
            case 8:
937
                ret = ldq_user(T0 & ~7);
938
                break;
939
            }
940
        }
941
        break;
942
    case 0x14: // Bypass
943
    case 0x15: // Bypass, non-cacheable
944
    case 0x1c: // Bypass LE
945
    case 0x1d: // Bypass, non-cacheable LE
946
        {
947
            switch(size) {
948
            case 1:
949
                ret = ldub_phys(T0);
950
                break;
951
            case 2:
952
                ret = lduw_phys(T0 & ~1);
953
                break;
954
            case 4:
955
                ret = ldl_phys(T0 & ~3);
956
                break;
957
            default:
958
            case 8:
959
                ret = ldq_phys(T0 & ~7);
960
                break;
961
            }
962
            break;
963
        }
964
    case 0x04: // Nucleus
965
    case 0x0c: // Nucleus Little Endian (LE)
966
    case 0x11: // As if user secondary
967
    case 0x19: // As if user secondary LE
968
    case 0x24: // Nucleus quad LDD 128 bit atomic
969
    case 0x2c: // Nucleus quad LDD 128 bit atomic
970
    case 0x4a: // UPA config
971
    case 0x81: // Secondary
972
    case 0x83: // Secondary no-fault
973
    case 0x89: // Secondary LE
974
    case 0x8b: // Secondary no-fault LE
975
        // XXX
976
        break;
977
    case 0x45: // LSU
978
        ret = env->lsu;
979
        break;
980
    case 0x50: // I-MMU regs
981
        {
982
            int reg = (T0 >> 3) & 0xf;
983

    
984
            ret = env->immuregs[reg];
985
            break;
986
        }
987
    case 0x51: // I-MMU 8k TSB pointer
988
    case 0x52: // I-MMU 64k TSB pointer
989
    case 0x55: // I-MMU data access
990
        // XXX
991
        break;
992
    case 0x56: // I-MMU tag read
993
        {
994
            unsigned int i;
995

    
996
            for (i = 0; i < 64; i++) {
997
                // Valid, ctx match, vaddr match
998
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
999
                    env->itlb_tag[i] == T0) {
1000
                    ret = env->itlb_tag[i];
1001
                    break;
1002
                }
1003
            }
1004
            break;
1005
        }
1006
    case 0x58: // D-MMU regs
1007
        {
1008
            int reg = (T0 >> 3) & 0xf;
1009

    
1010
            ret = env->dmmuregs[reg];
1011
            break;
1012
        }
1013
    case 0x5e: // D-MMU tag read
1014
        {
1015
            unsigned int i;
1016

    
1017
            for (i = 0; i < 64; i++) {
1018
                // Valid, ctx match, vaddr match
1019
                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
1020
                    env->dtlb_tag[i] == T0) {
1021
                    ret = env->dtlb_tag[i];
1022
                    break;
1023
                }
1024
            }
1025
            break;
1026
        }
1027
    case 0x59: // D-MMU 8k TSB pointer
1028
    case 0x5a: // D-MMU 64k TSB pointer
1029
    case 0x5b: // D-MMU data pointer
1030
    case 0x5d: // D-MMU data access
1031
    case 0x48: // Interrupt dispatch, RO
1032
    case 0x49: // Interrupt data receive
1033
    case 0x7f: // Incoming interrupt vector, RO
1034
        // XXX
1035
        break;
1036
    case 0x54: // I-MMU data in, WO
1037
    case 0x57: // I-MMU demap, WO
1038
    case 0x5c: // D-MMU data in, WO
1039
    case 0x5f: // D-MMU demap, WO
1040
    case 0x77: // Interrupt vector, WO
1041
    default:
1042
        do_unassigned_access(T0, 0, 0, 1);
1043
        ret = 0;
1044
        break;
1045
    }
1046

    
1047
    /* Convert from little endian */
1048
    switch (asi) {
1049
    case 0x0c: // Nucleus Little Endian (LE)
1050
    case 0x18: // As if user primary LE
1051
    case 0x19: // As if user secondary LE
1052
    case 0x1c: // Bypass LE
1053
    case 0x1d: // Bypass, non-cacheable LE
1054
    case 0x88: // Primary LE
1055
    case 0x89: // Secondary LE
1056
    case 0x8a: // Primary no-fault LE
1057
    case 0x8b: // Secondary no-fault LE
1058
        switch(size) {
1059
        case 2:
1060
            ret = bswap16(ret);
1061
            break;
1062
        case 4:
1063
            ret = bswap32(ret);
1064
            break;
1065
        case 8:
1066
            ret = bswap64(ret);
1067
            break;
1068
        default:
1069
            break;
1070
        }
1071
    default:
1072
        break;
1073
    }
1074

    
1075
    /* Convert to signed number */
1076
    if (sign) {
1077
        switch(size) {
1078
        case 1:
1079
            ret = (int8_t) ret;
1080
            break;
1081
        case 2:
1082
            ret = (int16_t) ret;
1083
            break;
1084
        case 4:
1085
            ret = (int32_t) ret;
1086
            break;
1087
        default:
1088
            break;
1089
        }
1090
    }
1091
    T1 = ret;
1092
}
1093

    
1094
void helper_st_asi(int asi, int size)
1095
{
1096
    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1097
        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
1098
        raise_exception(TT_PRIV_ACT);
1099

    
1100
    /* Convert to little endian */
1101
    switch (asi) {
1102
    case 0x0c: // Nucleus Little Endian (LE)
1103
    case 0x18: // As if user primary LE
1104
    case 0x19: // As if user secondary LE
1105
    case 0x1c: // Bypass LE
1106
    case 0x1d: // Bypass, non-cacheable LE
1107
    case 0x88: // Primary LE
1108
    case 0x89: // Secondary LE
1109
        switch(size) {
1110
        case 2:
1111
            T0 = bswap16(T0);
1112
            break;
1113
        case 4:
1114
            T0 = bswap32(T0);
1115
            break;
1116
        case 8:
1117
            T0 = bswap64(T0);
1118
            break;
1119
        default:
1120
            break;
1121
        }
1122
    default:
1123
        break;
1124
    }
1125

    
1126
    switch(asi) {
1127
    case 0x10: // As if user primary
1128
    case 0x18: // As if user primary LE
1129
    case 0x80: // Primary
1130
    case 0x88: // Primary LE
1131
        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1132
            if (env->hpstate & HS_PRIV) {
1133
                switch(size) {
1134
                case 1:
1135
                    stb_hypv(T0, T1);
1136
                    break;
1137
                case 2:
1138
                    stw_hypv(T0 & ~1, T1);
1139
                    break;
1140
                case 4:
1141
                    stl_hypv(T0 & ~3, T1);
1142
                    break;
1143
                case 8:
1144
                default:
1145
                    stq_hypv(T0 & ~7, T1);
1146
                    break;
1147
                }
1148
            } else {
1149
                switch(size) {
1150
                case 1:
1151
                    stb_kernel(T0, T1);
1152
                    break;
1153
                case 2:
1154
                    stw_kernel(T0 & ~1, T1);
1155
                    break;
1156
                case 4:
1157
                    stl_kernel(T0 & ~3, T1);
1158
                    break;
1159
                case 8:
1160
                default:
1161
                    stq_kernel(T0 & ~7, T1);
1162
                    break;
1163
                }
1164
            }
1165
        } else {
1166
            switch(size) {
1167
            case 1:
1168
                stb_user(T0, T1);
1169
                break;
1170
            case 2:
1171
                stw_user(T0 & ~1, T1);
1172
                break;
1173
            case 4:
1174
                stl_user(T0 & ~3, T1);
1175
                break;
1176
            case 8:
1177
            default:
1178
                stq_user(T0 & ~7, T1);
1179
                break;
1180
            }
1181
        }
1182
        break;
1183
    case 0x14: // Bypass
1184
    case 0x15: // Bypass, non-cacheable
1185
    case 0x1c: // Bypass LE
1186
    case 0x1d: // Bypass, non-cacheable LE
1187
        {
1188
            switch(size) {
1189
            case 1:
1190
                stb_phys(T0, T1);
1191
                break;
1192
            case 2:
1193
                stw_phys(T0 & ~1, T1);
1194
                break;
1195
            case 4:
1196
                stl_phys(T0 & ~3, T1);
1197
                break;
1198
            case 8:
1199
            default:
1200
                stq_phys(T0 & ~7, T1);
1201
                break;
1202
            }
1203
        }
1204
        return;
1205
    case 0x04: // Nucleus
1206
    case 0x0c: // Nucleus Little Endian (LE)
1207
    case 0x11: // As if user secondary
1208
    case 0x19: // As if user secondary LE
1209
    case 0x24: // Nucleus quad LDD 128 bit atomic
1210
    case 0x2c: // Nucleus quad LDD 128 bit atomic
1211
    case 0x4a: // UPA config
1212
    case 0x81: // Secondary
1213
    case 0x89: // Secondary LE
1214
        // XXX
1215
        return;
1216
    case 0x45: // LSU
1217
        {
1218
            uint64_t oldreg;
1219

    
1220
            oldreg = env->lsu;
1221
            env->lsu = T1 & (DMMU_E | IMMU_E);
1222
            // Mappings generated during D/I MMU disabled mode are
1223
            // invalid in normal mode
1224
            if (oldreg != env->lsu) {
1225
                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1226
#ifdef DEBUG_MMU
1227
                dump_mmu(env);
1228
#endif
1229
                tlb_flush(env, 1);
1230
            }
1231
            return;
1232
        }
1233
    case 0x50: // I-MMU regs
1234
        {
1235
            int reg = (T0 >> 3) & 0xf;
1236
            uint64_t oldreg;
1237

    
1238
            oldreg = env->immuregs[reg];
1239
            switch(reg) {
1240
            case 0: // RO
1241
            case 4:
1242
                return;
1243
            case 1: // Not in I-MMU
1244
            case 2:
1245
            case 7:
1246
            case 8:
1247
                return;
1248
            case 3: // SFSR
1249
                if ((T1 & 1) == 0)
1250
                    T1 = 0; // Clear SFSR
1251
                break;
1252
            case 5: // TSB access
1253
            case 6: // Tag access
1254
            default:
1255
                break;
1256
            }
1257
            env->immuregs[reg] = T1;
1258
            if (oldreg != env->immuregs[reg]) {
1259
                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1260
            }
1261
#ifdef DEBUG_MMU
1262
            dump_mmu(env);
1263
#endif
1264
            return;
1265
        }
1266
    case 0x54: // I-MMU data in
1267
        {
1268
            unsigned int i;
1269

    
1270
            // Try finding an invalid entry
1271
            for (i = 0; i < 64; i++) {
1272
                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
1273
                    env->itlb_tag[i] = env->immuregs[6];
1274
                    env->itlb_tte[i] = T1;
1275
                    return;
1276
                }
1277
            }
1278
            // Try finding an unlocked entry
1279
            for (i = 0; i < 64; i++) {
1280
                if ((env->itlb_tte[i] & 0x40) == 0) {
1281
                    env->itlb_tag[i] = env->immuregs[6];
1282
                    env->itlb_tte[i] = T1;
1283
                    return;
1284
                }
1285
            }
1286
            // error state?
1287
            return;
1288
        }
1289
    case 0x55: // I-MMU data access
1290
        {
1291
            unsigned int i = (T0 >> 3) & 0x3f;
1292

    
1293
            env->itlb_tag[i] = env->immuregs[6];
1294
            env->itlb_tte[i] = T1;
1295
            return;
1296
        }
1297
    case 0x57: // I-MMU demap
1298
        // XXX
1299
        return;
1300
    case 0x58: // D-MMU regs
1301
        {
1302
            int reg = (T0 >> 3) & 0xf;
1303
            uint64_t oldreg;
1304

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

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

    
1362
            env->dtlb_tag[i] = env->dmmuregs[6];
1363
            env->dtlb_tte[i] = T1;
1364
            return;
1365
        }
1366
    case 0x5f: // D-MMU demap
1367
    case 0x49: // Interrupt data receive
1368
        // XXX
1369
        return;
1370
    case 0x51: // I-MMU 8k TSB pointer, RO
1371
    case 0x52: // I-MMU 64k TSB pointer, RO
1372
    case 0x56: // I-MMU tag read, RO
1373
    case 0x59: // D-MMU 8k TSB pointer, RO
1374
    case 0x5a: // D-MMU 64k TSB pointer, RO
1375
    case 0x5b: // D-MMU data pointer, RO
1376
    case 0x5e: // D-MMU tag read, RO
1377
    case 0x48: // Interrupt dispatch, RO
1378
    case 0x7f: // Incoming interrupt vector, RO
1379
    case 0x82: // Primary no-fault, RO
1380
    case 0x83: // Secondary no-fault, RO
1381
    case 0x8a: // Primary no-fault LE, RO
1382
    case 0x8b: // Secondary no-fault LE, RO
1383
    default:
1384
        do_unassigned_access(T0, 1, 0, 1);
1385
        return;
1386
    }
1387
}
1388
#endif /* CONFIG_USER_ONLY */
1389

    
1390
void helper_ldf_asi(int asi, int size, int rd)
1391
{
1392
    target_ulong tmp_T0 = T0, tmp_T1 = T1;
1393
    unsigned int i;
1394

    
1395
    switch (asi) {
1396
    case 0xf0: // Block load primary
1397
    case 0xf1: // Block load secondary
1398
    case 0xf8: // Block load primary LE
1399
    case 0xf9: // Block load secondary LE
1400
        if (rd & 7) {
1401
            raise_exception(TT_ILL_INSN);
1402
            return;
1403
        }
1404
        if (T0 & 0x3f) {
1405
            raise_exception(TT_UNALIGNED);
1406
            return;
1407
        }
1408
        for (i = 0; i < 16; i++) {
1409
            helper_ld_asi(asi & 0x8f, 4, 0);
1410
            *(uint32_t *)&env->fpr[rd++] = T1;
1411
            T0 += 4;
1412
        }
1413
        T0 = tmp_T0;
1414
        T1 = tmp_T1;
1415

    
1416
        return;
1417
    default:
1418
        break;
1419
    }
1420

    
1421
    helper_ld_asi(asi, size, 0);
1422
    switch(size) {
1423
    default:
1424
    case 4:
1425
        *((uint32_t *)&FT0) = T1;
1426
        break;
1427
    case 8:
1428
        *((int64_t *)&DT0) = T1;
1429
        break;
1430
#if defined(CONFIG_USER_ONLY)
1431
    case 16:
1432
        // XXX
1433
        break;
1434
#endif
1435
    }
1436
    T1 = tmp_T1;
1437
}
1438

    
1439
void helper_stf_asi(int asi, int size, int rd)
1440
{
1441
    target_ulong tmp_T0 = T0, tmp_T1 = T1;
1442
    unsigned int i;
1443

    
1444
    switch (asi) {
1445
    case 0xf0: // Block store primary
1446
    case 0xf1: // Block store secondary
1447
    case 0xf8: // Block store primary LE
1448
    case 0xf9: // Block store secondary LE
1449
        if (rd & 7) {
1450
            raise_exception(TT_ILL_INSN);
1451
            return;
1452
        }
1453
        if (T0 & 0x3f) {
1454
            raise_exception(TT_UNALIGNED);
1455
            return;
1456
        }
1457
        for (i = 0; i < 16; i++) {
1458
            T1 = *(uint32_t *)&env->fpr[rd++];
1459
            helper_st_asi(asi & 0x8f, 4);
1460
            T0 += 4;
1461
        }
1462
        T0 = tmp_T0;
1463
        T1 = tmp_T1;
1464

    
1465
        return;
1466
    default:
1467
        break;
1468
    }
1469

    
1470
    switch(size) {
1471
    default:
1472
    case 4:
1473
        T1 = *((uint32_t *)&FT0);
1474
        break;
1475
    case 8:
1476
        T1 = *((int64_t *)&DT0);
1477
        break;
1478
#if defined(CONFIG_USER_ONLY)
1479
    case 16:
1480
        // XXX
1481
        break;
1482
#endif
1483
    }
1484
    helper_st_asi(asi, size);
1485
    T1 = tmp_T1;
1486
}
1487

    
1488
#endif /* TARGET_SPARC64 */
1489

    
1490
#ifndef TARGET_SPARC64
1491
void helper_rett()
1492
{
1493
    unsigned int cwp;
1494

    
1495
    if (env->psret == 1)
1496
        raise_exception(TT_ILL_INSN);
1497

    
1498
    env->psret = 1;
1499
    cwp = (env->cwp + 1) & (NWINDOWS - 1);
1500
    if (env->wim & (1 << cwp)) {
1501
        raise_exception(TT_WIN_UNF);
1502
    }
1503
    set_cwp(cwp);
1504
    env->psrs = env->psrps;
1505
}
1506
#endif
1507

    
1508
void helper_ldfsr(void)
1509
{
1510
    int rnd_mode;
1511
    switch (env->fsr & FSR_RD_MASK) {
1512
    case FSR_RD_NEAREST:
1513
        rnd_mode = float_round_nearest_even;
1514
        break;
1515
    default:
1516
    case FSR_RD_ZERO:
1517
        rnd_mode = float_round_to_zero;
1518
        break;
1519
    case FSR_RD_POS:
1520
        rnd_mode = float_round_up;
1521
        break;
1522
    case FSR_RD_NEG:
1523
        rnd_mode = float_round_down;
1524
        break;
1525
    }
1526
    set_float_rounding_mode(rnd_mode, &env->fp_status);
1527
}
1528

    
1529
void helper_debug()
1530
{
1531
    env->exception_index = EXCP_DEBUG;
1532
    cpu_loop_exit();
1533
}
1534

    
1535
#ifndef TARGET_SPARC64
1536
void do_wrpsr()
1537
{
1538
    if ((T0 & PSR_CWP) >= NWINDOWS)
1539
        raise_exception(TT_ILL_INSN);
1540
    else
1541
        PUT_PSR(env, T0);
1542
}
1543

    
1544
void do_rdpsr()
1545
{
1546
    T0 = GET_PSR(env);
1547
}
1548

    
1549
#else
1550

    
1551
void do_popc()
1552
{
1553
    T0 = ctpop64(T1);
1554
}
1555

    
1556
static inline uint64_t *get_gregset(uint64_t pstate)
1557
{
1558
    switch (pstate) {
1559
    default:
1560
    case 0:
1561
        return env->bgregs;
1562
    case PS_AG:
1563
        return env->agregs;
1564
    case PS_MG:
1565
        return env->mgregs;
1566
    case PS_IG:
1567
        return env->igregs;
1568
    }
1569
}
1570

    
1571
static inline void change_pstate(uint64_t new_pstate)
1572
{
1573
    uint64_t pstate_regs, new_pstate_regs;
1574
    uint64_t *src, *dst;
1575

    
1576
    pstate_regs = env->pstate & 0xc01;
1577
    new_pstate_regs = new_pstate & 0xc01;
1578
    if (new_pstate_regs != pstate_regs) {
1579
        // Switch global register bank
1580
        src = get_gregset(new_pstate_regs);
1581
        dst = get_gregset(pstate_regs);
1582
        memcpy32(dst, env->gregs);
1583
        memcpy32(env->gregs, src);
1584
    }
1585
    env->pstate = new_pstate;
1586
}
1587

    
1588
void do_wrpstate(void)
1589
{
1590
    change_pstate(T0 & 0xf3f);
1591
}
1592

    
1593
void do_done(void)
1594
{
1595
    env->tl--;
1596
    env->pc = env->tnpc[env->tl];
1597
    env->npc = env->tnpc[env->tl] + 4;
1598
    PUT_CCR(env, env->tstate[env->tl] >> 32);
1599
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1600
    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1601
    PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1602
}
1603

    
1604
void do_retry(void)
1605
{
1606
    env->tl--;
1607
    env->pc = env->tpc[env->tl];
1608
    env->npc = env->tnpc[env->tl];
1609
    PUT_CCR(env, env->tstate[env->tl] >> 32);
1610
    env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1611
    change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
1612
    PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1613
}
1614
#endif
1615

    
1616
void set_cwp(int new_cwp)
1617
{
1618
    /* put the modified wrap registers at their proper location */
1619
    if (env->cwp == (NWINDOWS - 1))
1620
        memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
1621
    env->cwp = new_cwp;
1622
    /* put the wrap registers at their temporary location */
1623
    if (new_cwp == (NWINDOWS - 1))
1624
        memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
1625
    env->regwptr = env->regbase + (new_cwp * 16);
1626
    REGWPTR = env->regwptr;
1627
}
1628

    
1629
void cpu_set_cwp(CPUState *env1, int new_cwp)
1630
{
1631
    CPUState *saved_env;
1632
#ifdef reg_REGWPTR
1633
    target_ulong *saved_regwptr;
1634
#endif
1635

    
1636
    saved_env = env;
1637
#ifdef reg_REGWPTR
1638
    saved_regwptr = REGWPTR;
1639
#endif
1640
    env = env1;
1641
    set_cwp(new_cwp);
1642
    env = saved_env;
1643
#ifdef reg_REGWPTR
1644
    REGWPTR = saved_regwptr;
1645
#endif
1646
}
1647

    
1648
#ifdef TARGET_SPARC64
1649
void do_interrupt(int intno)
1650
{
1651
#ifdef DEBUG_PCALL
1652
    if (loglevel & CPU_LOG_INT) {
1653
        static int count;
1654
        fprintf(logfile, "%6d: v=%04x pc=%016" PRIx64 " npc=%016" PRIx64 " SP=%016" PRIx64 "\n",
1655
                count, intno,
1656
                env->pc,
1657
                env->npc, env->regwptr[6]);
1658
        cpu_dump_state(env, logfile, fprintf, 0);
1659
#if 0
1660
        {
1661
            int i;
1662
            uint8_t *ptr;
1663

1664
            fprintf(logfile, "       code=");
1665
            ptr = (uint8_t *)env->pc;
1666
            for(i = 0; i < 16; i++) {
1667
                fprintf(logfile, " %02x", ldub(ptr + i));
1668
            }
1669
            fprintf(logfile, "\n");
1670
        }
1671
#endif
1672
        count++;
1673
    }
1674
#endif
1675
#if !defined(CONFIG_USER_ONLY)
1676
    if (env->tl == MAXTL) {
1677
        cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1678
        return;
1679
    }
1680
#endif
1681
    env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
1682
        ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
1683
    env->tpc[env->tl] = env->pc;
1684
    env->tnpc[env->tl] = env->npc;
1685
    env->tt[env->tl] = intno;
1686
    change_pstate(PS_PEF | PS_PRIV | PS_AG);
1687

    
1688
    if (intno == TT_CLRWIN)
1689
        set_cwp((env->cwp - 1) & (NWINDOWS - 1));
1690
    else if ((intno & 0x1c0) == TT_SPILL)
1691
        set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
1692
    else if ((intno & 0x1c0) == TT_FILL)
1693
        set_cwp((env->cwp + 1) & (NWINDOWS - 1));
1694
    env->tbr &= ~0x7fffULL;
1695
    env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1696
    if (env->tl < MAXTL - 1) {
1697
        env->tl++;
1698
    } else {
1699
        env->pstate |= PS_RED;
1700
        if (env->tl != MAXTL)
1701
            env->tl++;
1702
    }
1703
    env->pc = env->tbr;
1704
    env->npc = env->pc + 4;
1705
    env->exception_index = 0;
1706
}
1707
#else
1708
void do_interrupt(int intno)
1709
{
1710
    int cwp;
1711

    
1712
#ifdef DEBUG_PCALL
1713
    if (loglevel & CPU_LOG_INT) {
1714
        static int count;
1715
        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
1716
                count, intno,
1717
                env->pc,
1718
                env->npc, env->regwptr[6]);
1719
        cpu_dump_state(env, logfile, fprintf, 0);
1720
#if 0
1721
        {
1722
            int i;
1723
            uint8_t *ptr;
1724

1725
            fprintf(logfile, "       code=");
1726
            ptr = (uint8_t *)env->pc;
1727
            for(i = 0; i < 16; i++) {
1728
                fprintf(logfile, " %02x", ldub(ptr + i));
1729
            }
1730
            fprintf(logfile, "\n");
1731
        }
1732
#endif
1733
        count++;
1734
    }
1735
#endif
1736
#if !defined(CONFIG_USER_ONLY)
1737
    if (env->psret == 0) {
1738
        cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1739
        return;
1740
    }
1741
#endif
1742
    env->psret = 0;
1743
    cwp = (env->cwp - 1) & (NWINDOWS - 1);
1744
    set_cwp(cwp);
1745
    env->regwptr[9] = env->pc;
1746
    env->regwptr[10] = env->npc;
1747
    env->psrps = env->psrs;
1748
    env->psrs = 1;
1749
    env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
1750
    env->pc = env->tbr;
1751
    env->npc = env->pc + 4;
1752
    env->exception_index = 0;
1753
}
1754
#endif
1755

    
1756
#if !defined(CONFIG_USER_ONLY)
1757

    
1758
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1759
                                void *retaddr);
1760

    
1761
#define MMUSUFFIX _mmu
1762
#define ALIGNED_ONLY
1763
#ifdef __s390__
1764
# define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
1765
#else
1766
# define GETPC() (__builtin_return_address(0))
1767
#endif
1768

    
1769
#define SHIFT 0
1770
#include "softmmu_template.h"
1771

    
1772
#define SHIFT 1
1773
#include "softmmu_template.h"
1774

    
1775
#define SHIFT 2
1776
#include "softmmu_template.h"
1777

    
1778
#define SHIFT 3
1779
#include "softmmu_template.h"
1780

    
1781
static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
1782
                                void *retaddr)
1783
{
1784
#ifdef DEBUG_UNALIGNED
1785
    printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
1786
#endif
1787
    raise_exception(TT_UNALIGNED);
1788
}
1789

    
1790
/* try to fill the TLB and return an exception if error. If retaddr is
1791
   NULL, it means that the function was called in C code (i.e. not
1792
   from generated code or from helper.c) */
1793
/* XXX: fix it to restore all registers */
1794
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1795
{
1796
    TranslationBlock *tb;
1797
    int ret;
1798
    unsigned long pc;
1799
    CPUState *saved_env;
1800

    
1801
    /* XXX: hack to restore env in all cases, even if not called from
1802
       generated code */
1803
    saved_env = env;
1804
    env = cpu_single_env;
1805

    
1806
    ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1807
    if (ret) {
1808
        if (retaddr) {
1809
            /* now we have a real cpu fault */
1810
            pc = (unsigned long)retaddr;
1811
            tb = tb_find_pc(pc);
1812
            if (tb) {
1813
                /* the PC is inside the translated code. It means that we have
1814
                   a virtual CPU fault */
1815
                cpu_restore_state(tb, env, pc, (void *)T2);
1816
            }
1817
        }
1818
        cpu_loop_exit();
1819
    }
1820
    env = saved_env;
1821
}
1822

    
1823
#endif
1824

    
1825
#ifndef TARGET_SPARC64
1826
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1827
                          int is_asi)
1828
{
1829
    CPUState *saved_env;
1830

    
1831
    /* XXX: hack to restore env in all cases, even if not called from
1832
       generated code */
1833
    saved_env = env;
1834
    env = cpu_single_env;
1835
    if (env->mmuregs[3]) /* Fault status register */
1836
        env->mmuregs[3] = 1; /* overflow (not read before another fault) */
1837
    if (is_asi)
1838
        env->mmuregs[3] |= 1 << 16;
1839
    if (env->psrs)
1840
        env->mmuregs[3] |= 1 << 5;
1841
    if (is_exec)
1842
        env->mmuregs[3] |= 1 << 6;
1843
    if (is_write)
1844
        env->mmuregs[3] |= 1 << 7;
1845
    env->mmuregs[3] |= (5 << 2) | 2;
1846
    env->mmuregs[4] = addr; /* Fault address register */
1847
    if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
1848
#ifdef DEBUG_UNASSIGNED
1849
        printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
1850
               "\n", addr, env->pc);
1851
#endif
1852
        if (is_exec)
1853
            raise_exception(TT_CODE_ACCESS);
1854
        else
1855
            raise_exception(TT_DATA_ACCESS);
1856
    }
1857
    env = saved_env;
1858
}
1859
#else
1860
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1861
                          int is_asi)
1862
{
1863
#ifdef DEBUG_UNASSIGNED
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
    printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
1871
           addr, env->pc);
1872
    env = saved_env;
1873
#endif
1874
    if (is_exec)
1875
        raise_exception(TT_CODE_ACCESS);
1876
    else
1877
        raise_exception(TT_DATA_ACCESS);
1878
}
1879
#endif
1880