Annotation of qemu/target-sparc/op_helper.c, revision 1.1.1.6

1.1       root        1: #include "exec.h"
1.1.1.5   root        2: #include "host-utils.h"
1.1.1.6 ! root        3: #include "helper.h"
        !             4: #if !defined(CONFIG_USER_ONLY)
        !             5: #include "softmmu_exec.h"
        !             6: #endif /* !defined(CONFIG_USER_ONLY) */
1.1       root        7: 
                      8: //#define DEBUG_MMU
1.1.1.5   root        9: //#define DEBUG_MXCC
                     10: //#define DEBUG_UNALIGNED
                     11: //#define DEBUG_UNASSIGNED
                     12: //#define DEBUG_ASI
1.1.1.6 ! root       13: //#define DEBUG_PCALL
1.1.1.5   root       14: 
                     15: #ifdef DEBUG_MMU
                     16: #define DPRINTF_MMU(fmt, args...) \
                     17: do { printf("MMU: " fmt , ##args); } while (0)
                     18: #else
1.1.1.6 ! root       19: #define DPRINTF_MMU(fmt, args...) do {} while (0)
1.1.1.5   root       20: #endif
                     21: 
                     22: #ifdef DEBUG_MXCC
                     23: #define DPRINTF_MXCC(fmt, args...) \
                     24: do { printf("MXCC: " fmt , ##args); } while (0)
                     25: #else
1.1.1.6 ! root       26: #define DPRINTF_MXCC(fmt, args...) do {} while (0)
1.1.1.5   root       27: #endif
                     28: 
                     29: #ifdef DEBUG_ASI
                     30: #define DPRINTF_ASI(fmt, args...) \
                     31: do { printf("ASI: " fmt , ##args); } while (0)
                     32: #else
1.1.1.6 ! root       33: #define DPRINTF_ASI(fmt, args...) do {} while (0)
        !            34: #endif
        !            35: 
        !            36: #ifdef TARGET_SPARC64
        !            37: #ifndef TARGET_ABI32
        !            38: #define AM_CHECK(env1) ((env1)->pstate & PS_AM)
        !            39: #else
        !            40: #define AM_CHECK(env1) (1)
        !            41: #endif
1.1.1.5   root       42: #endif
1.1       root       43: 
1.1.1.6 ! root       44: static inline void address_mask(CPUState *env1, target_ulong *addr)
        !            45: {
        !            46: #ifdef TARGET_SPARC64
        !            47:     if (AM_CHECK(env1))
        !            48:         *addr &= 0xffffffffULL;
        !            49: #endif
        !            50: }
        !            51: 
        !            52: static void raise_exception(int tt)
1.1       root       53: {
                     54:     env->exception_index = tt;
                     55:     cpu_loop_exit();
1.1.1.5   root       56: }
                     57: 
1.1.1.6 ! root       58: void HELPER(raise_exception)(int tt)
1.1.1.5   root       59: {
1.1.1.6 ! root       60:     raise_exception(tt);
        !            61: }
1.1.1.5   root       62: 
1.1.1.6 ! root       63: static inline void set_cwp(int new_cwp)
        !            64: {
        !            65:     cpu_set_cwp(env, new_cwp);
1.1.1.5   root       66: }
1.1       root       67: 
1.1.1.6 ! root       68: void helper_check_align(target_ulong addr, uint32_t align)
1.1       root       69: {
1.1.1.6 ! root       70:     if (addr & align) {
        !            71: #ifdef DEBUG_UNALIGNED
        !            72:     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
        !            73:            "\n", addr, env->pc);
        !            74: #endif
        !            75:         raise_exception(TT_UNALIGNED);
        !            76:     }
        !            77: }
        !            78: 
        !            79: #define F_HELPER(name, p) void helper_f##name##p(void)
        !            80: 
        !            81: #define F_BINOP(name)                                           \
        !            82:     float32 helper_f ## name ## s (float32 src1, float32 src2)  \
        !            83:     {                                                           \
        !            84:         return float32_ ## name (src1, src2, &env->fp_status);  \
        !            85:     }                                                           \
        !            86:     F_HELPER(name, d)                                           \
        !            87:     {                                                           \
        !            88:         DT0 = float64_ ## name (DT0, DT1, &env->fp_status);     \
        !            89:     }                                                           \
        !            90:     F_HELPER(name, q)                                           \
        !            91:     {                                                           \
        !            92:         QT0 = float128_ ## name (QT0, QT1, &env->fp_status);    \
        !            93:     }
        !            94: 
        !            95: F_BINOP(add);
        !            96: F_BINOP(sub);
        !            97: F_BINOP(mul);
        !            98: F_BINOP(div);
        !            99: #undef F_BINOP
        !           100: 
        !           101: void helper_fsmuld(float32 src1, float32 src2)
        !           102: {
        !           103:     DT0 = float64_mul(float32_to_float64(src1, &env->fp_status),
        !           104:                       float32_to_float64(src2, &env->fp_status),
        !           105:                       &env->fp_status);
        !           106: }
        !           107: 
        !           108: void helper_fdmulq(void)
        !           109: {
        !           110:     QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status),
        !           111:                        float64_to_float128(DT1, &env->fp_status),
        !           112:                        &env->fp_status);
        !           113: }
        !           114: 
        !           115: float32 helper_fnegs(float32 src)
        !           116: {
        !           117:     return float32_chs(src);
1.1       root      118: }
                    119: 
1.1.1.6 ! root      120: #ifdef TARGET_SPARC64
        !           121: F_HELPER(neg, d)
1.1       root      122: {
1.1.1.6 ! root      123:     DT0 = float64_chs(DT1);
1.1       root      124: }
1.1.1.5   root      125: 
1.1.1.6 ! root      126: F_HELPER(neg, q)
1.1.1.5   root      127: {
1.1.1.6 ! root      128:     QT0 = float128_chs(QT1);
1.1.1.5   root      129: }
                    130: #endif
                    131: 
1.1.1.6 ! root      132: /* Integer to float conversion.  */
        !           133: float32 helper_fitos(int32_t src)
        !           134: {
        !           135:     return int32_to_float32(src, &env->fp_status);
        !           136: }
        !           137: 
        !           138: void helper_fitod(int32_t src)
        !           139: {
        !           140:     DT0 = int32_to_float64(src, &env->fp_status);
        !           141: }
        !           142: 
        !           143: void helper_fitoq(int32_t src)
        !           144: {
        !           145:     QT0 = int32_to_float128(src, &env->fp_status);
        !           146: }
        !           147: 
1.1.1.5   root      148: #ifdef TARGET_SPARC64
1.1.1.6 ! root      149: float32 helper_fxtos(void)
1.1.1.5   root      150: {
1.1.1.6 ! root      151:     return int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
1.1.1.5   root      152: }
                    153: 
1.1.1.6 ! root      154: F_HELPER(xto, d)
1.1.1.5   root      155: {
                    156:     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
                    157: }
                    158: 
1.1.1.6 ! root      159: F_HELPER(xto, q)
1.1.1.5   root      160: {
1.1.1.6 ! root      161:     QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status);
1.1.1.5   root      162: }
                    163: #endif
1.1.1.6 ! root      164: #undef F_HELPER
        !           165: 
        !           166: /* floating point conversion */
        !           167: float32 helper_fdtos(void)
        !           168: {
        !           169:     return float64_to_float32(DT1, &env->fp_status);
        !           170: }
        !           171: 
        !           172: void helper_fstod(float32 src)
        !           173: {
        !           174:     DT0 = float32_to_float64(src, &env->fp_status);
        !           175: }
        !           176: 
        !           177: float32 helper_fqtos(void)
        !           178: {
        !           179:     return float128_to_float32(QT1, &env->fp_status);
        !           180: }
        !           181: 
        !           182: void helper_fstoq(float32 src)
        !           183: {
        !           184:     QT0 = float32_to_float128(src, &env->fp_status);
        !           185: }
        !           186: 
        !           187: void helper_fqtod(void)
        !           188: {
        !           189:     DT0 = float128_to_float64(QT1, &env->fp_status);
        !           190: }
        !           191: 
        !           192: void helper_fdtoq(void)
        !           193: {
        !           194:     QT0 = float64_to_float128(DT1, &env->fp_status);
        !           195: }
        !           196: 
        !           197: /* Float to integer conversion.  */
        !           198: int32_t helper_fstoi(float32 src)
        !           199: {
        !           200:     return float32_to_int32_round_to_zero(src, &env->fp_status);
        !           201: }
        !           202: 
        !           203: int32_t helper_fdtoi(void)
        !           204: {
        !           205:     return float64_to_int32_round_to_zero(DT1, &env->fp_status);
        !           206: }
        !           207: 
        !           208: int32_t helper_fqtoi(void)
        !           209: {
        !           210:     return float128_to_int32_round_to_zero(QT1, &env->fp_status);
        !           211: }
        !           212: 
        !           213: #ifdef TARGET_SPARC64
        !           214: void helper_fstox(float32 src)
        !           215: {
        !           216:     *((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status);
        !           217: }
        !           218: 
        !           219: void helper_fdtox(void)
        !           220: {
        !           221:     *((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status);
        !           222: }
        !           223: 
        !           224: void helper_fqtox(void)
        !           225: {
        !           226:     *((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status);
        !           227: }
        !           228: 
        !           229: void helper_faligndata(void)
        !           230: {
        !           231:     uint64_t tmp;
        !           232: 
        !           233:     tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
        !           234:     /* on many architectures a shift of 64 does nothing */
        !           235:     if ((env->gsr & 7) != 0) {
        !           236:         tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
        !           237:     }
        !           238:     *((uint64_t *)&DT0) = tmp;
        !           239: }
        !           240: 
        !           241: #ifdef WORDS_BIGENDIAN
        !           242: #define VIS_B64(n) b[7 - (n)]
        !           243: #define VIS_W64(n) w[3 - (n)]
        !           244: #define VIS_SW64(n) sw[3 - (n)]
        !           245: #define VIS_L64(n) l[1 - (n)]
        !           246: #define VIS_B32(n) b[3 - (n)]
        !           247: #define VIS_W32(n) w[1 - (n)]
        !           248: #else
        !           249: #define VIS_B64(n) b[n]
        !           250: #define VIS_W64(n) w[n]
        !           251: #define VIS_SW64(n) sw[n]
        !           252: #define VIS_L64(n) l[n]
        !           253: #define VIS_B32(n) b[n]
        !           254: #define VIS_W32(n) w[n]
        !           255: #endif
        !           256: 
        !           257: typedef union {
        !           258:     uint8_t b[8];
        !           259:     uint16_t w[4];
        !           260:     int16_t sw[4];
        !           261:     uint32_t l[2];
        !           262:     float64 d;
        !           263: } vis64;
        !           264: 
        !           265: typedef union {
        !           266:     uint8_t b[4];
        !           267:     uint16_t w[2];
        !           268:     uint32_t l;
        !           269:     float32 f;
        !           270: } vis32;
        !           271: 
        !           272: void helper_fpmerge(void)
        !           273: {
        !           274:     vis64 s, d;
        !           275: 
        !           276:     s.d = DT0;
        !           277:     d.d = DT1;
        !           278: 
        !           279:     // Reverse calculation order to handle overlap
        !           280:     d.VIS_B64(7) = s.VIS_B64(3);
        !           281:     d.VIS_B64(6) = d.VIS_B64(3);
        !           282:     d.VIS_B64(5) = s.VIS_B64(2);
        !           283:     d.VIS_B64(4) = d.VIS_B64(2);
        !           284:     d.VIS_B64(3) = s.VIS_B64(1);
        !           285:     d.VIS_B64(2) = d.VIS_B64(1);
        !           286:     d.VIS_B64(1) = s.VIS_B64(0);
        !           287:     //d.VIS_B64(0) = d.VIS_B64(0);
        !           288: 
        !           289:     DT0 = d.d;
        !           290: }
        !           291: 
        !           292: void helper_fmul8x16(void)
        !           293: {
        !           294:     vis64 s, d;
        !           295:     uint32_t tmp;
        !           296: 
        !           297:     s.d = DT0;
        !           298:     d.d = DT1;
        !           299: 
        !           300: #define PMUL(r)                                                 \
        !           301:     tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r);       \
        !           302:     if ((tmp & 0xff) > 0x7f)                                    \
        !           303:         tmp += 0x100;                                           \
        !           304:     d.VIS_W64(r) = tmp >> 8;
        !           305: 
        !           306:     PMUL(0);
        !           307:     PMUL(1);
        !           308:     PMUL(2);
        !           309:     PMUL(3);
        !           310: #undef PMUL
        !           311: 
        !           312:     DT0 = d.d;
        !           313: }
        !           314: 
        !           315: void helper_fmul8x16al(void)
        !           316: {
        !           317:     vis64 s, d;
        !           318:     uint32_t tmp;
        !           319: 
        !           320:     s.d = DT0;
        !           321:     d.d = DT1;
        !           322: 
        !           323: #define PMUL(r)                                                 \
        !           324:     tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r);       \
        !           325:     if ((tmp & 0xff) > 0x7f)                                    \
        !           326:         tmp += 0x100;                                           \
        !           327:     d.VIS_W64(r) = tmp >> 8;
        !           328: 
        !           329:     PMUL(0);
        !           330:     PMUL(1);
        !           331:     PMUL(2);
        !           332:     PMUL(3);
        !           333: #undef PMUL
        !           334: 
        !           335:     DT0 = d.d;
        !           336: }
        !           337: 
        !           338: void helper_fmul8x16au(void)
        !           339: {
        !           340:     vis64 s, d;
        !           341:     uint32_t tmp;
        !           342: 
        !           343:     s.d = DT0;
        !           344:     d.d = DT1;
        !           345: 
        !           346: #define PMUL(r)                                                 \
        !           347:     tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r);       \
        !           348:     if ((tmp & 0xff) > 0x7f)                                    \
        !           349:         tmp += 0x100;                                           \
        !           350:     d.VIS_W64(r) = tmp >> 8;
        !           351: 
        !           352:     PMUL(0);
        !           353:     PMUL(1);
        !           354:     PMUL(2);
        !           355:     PMUL(3);
        !           356: #undef PMUL
        !           357: 
        !           358:     DT0 = d.d;
        !           359: }
        !           360: 
        !           361: void helper_fmul8sux16(void)
        !           362: {
        !           363:     vis64 s, d;
        !           364:     uint32_t tmp;
        !           365: 
        !           366:     s.d = DT0;
        !           367:     d.d = DT1;
        !           368: 
        !           369: #define PMUL(r)                                                         \
        !           370:     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
        !           371:     if ((tmp & 0xff) > 0x7f)                                            \
        !           372:         tmp += 0x100;                                                   \
        !           373:     d.VIS_W64(r) = tmp >> 8;
        !           374: 
        !           375:     PMUL(0);
        !           376:     PMUL(1);
        !           377:     PMUL(2);
        !           378:     PMUL(3);
        !           379: #undef PMUL
        !           380: 
        !           381:     DT0 = d.d;
        !           382: }
        !           383: 
        !           384: void helper_fmul8ulx16(void)
        !           385: {
        !           386:     vis64 s, d;
        !           387:     uint32_t tmp;
        !           388: 
        !           389:     s.d = DT0;
        !           390:     d.d = DT1;
        !           391: 
        !           392: #define PMUL(r)                                                         \
        !           393:     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
        !           394:     if ((tmp & 0xff) > 0x7f)                                            \
        !           395:         tmp += 0x100;                                                   \
        !           396:     d.VIS_W64(r) = tmp >> 8;
        !           397: 
        !           398:     PMUL(0);
        !           399:     PMUL(1);
        !           400:     PMUL(2);
        !           401:     PMUL(3);
        !           402: #undef PMUL
        !           403: 
        !           404:     DT0 = d.d;
        !           405: }
        !           406: 
        !           407: void helper_fmuld8sux16(void)
        !           408: {
        !           409:     vis64 s, d;
        !           410:     uint32_t tmp;
        !           411: 
        !           412:     s.d = DT0;
        !           413:     d.d = DT1;
        !           414: 
        !           415: #define PMUL(r)                                                         \
        !           416:     tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8);       \
        !           417:     if ((tmp & 0xff) > 0x7f)                                            \
        !           418:         tmp += 0x100;                                                   \
        !           419:     d.VIS_L64(r) = tmp;
        !           420: 
        !           421:     // Reverse calculation order to handle overlap
        !           422:     PMUL(1);
        !           423:     PMUL(0);
        !           424: #undef PMUL
        !           425: 
        !           426:     DT0 = d.d;
        !           427: }
        !           428: 
        !           429: void helper_fmuld8ulx16(void)
        !           430: {
        !           431:     vis64 s, d;
        !           432:     uint32_t tmp;
        !           433: 
        !           434:     s.d = DT0;
        !           435:     d.d = DT1;
        !           436: 
        !           437: #define PMUL(r)                                                         \
        !           438:     tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2));        \
        !           439:     if ((tmp & 0xff) > 0x7f)                                            \
        !           440:         tmp += 0x100;                                                   \
        !           441:     d.VIS_L64(r) = tmp;
        !           442: 
        !           443:     // Reverse calculation order to handle overlap
        !           444:     PMUL(1);
        !           445:     PMUL(0);
        !           446: #undef PMUL
        !           447: 
        !           448:     DT0 = d.d;
        !           449: }
        !           450: 
        !           451: void helper_fexpand(void)
        !           452: {
        !           453:     vis32 s;
        !           454:     vis64 d;
        !           455: 
        !           456:     s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff);
        !           457:     d.d = DT1;
        !           458:     d.VIS_W64(0) = s.VIS_B32(0) << 4;
        !           459:     d.VIS_W64(1) = s.VIS_B32(1) << 4;
        !           460:     d.VIS_W64(2) = s.VIS_B32(2) << 4;
        !           461:     d.VIS_W64(3) = s.VIS_B32(3) << 4;
        !           462: 
        !           463:     DT0 = d.d;
        !           464: }
        !           465: 
        !           466: #define VIS_HELPER(name, F)                             \
        !           467:     void name##16(void)                                 \
        !           468:     {                                                   \
        !           469:         vis64 s, d;                                     \
        !           470:                                                         \
        !           471:         s.d = DT0;                                      \
        !           472:         d.d = DT1;                                      \
        !           473:                                                         \
        !           474:         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0));   \
        !           475:         d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1));   \
        !           476:         d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2));   \
        !           477:         d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3));   \
        !           478:                                                         \
        !           479:         DT0 = d.d;                                      \
        !           480:     }                                                   \
        !           481:                                                         \
        !           482:     uint32_t name##16s(uint32_t src1, uint32_t src2)    \
        !           483:     {                                                   \
        !           484:         vis32 s, d;                                     \
        !           485:                                                         \
        !           486:         s.l = src1;                                     \
        !           487:         d.l = src2;                                     \
        !           488:                                                         \
        !           489:         d.VIS_W32(0) = F(d.VIS_W32(0), s.VIS_W32(0));   \
        !           490:         d.VIS_W32(1) = F(d.VIS_W32(1), s.VIS_W32(1));   \
        !           491:                                                         \
        !           492:         return d.l;                                     \
        !           493:     }                                                   \
        !           494:                                                         \
        !           495:     void name##32(void)                                 \
        !           496:     {                                                   \
        !           497:         vis64 s, d;                                     \
        !           498:                                                         \
        !           499:         s.d = DT0;                                      \
        !           500:         d.d = DT1;                                      \
        !           501:                                                         \
        !           502:         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0));   \
        !           503:         d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1));   \
        !           504:                                                         \
        !           505:         DT0 = d.d;                                      \
        !           506:     }                                                   \
        !           507:                                                         \
        !           508:     uint32_t name##32s(uint32_t src1, uint32_t src2)    \
        !           509:     {                                                   \
        !           510:         vis32 s, d;                                     \
        !           511:                                                         \
        !           512:         s.l = src1;                                     \
        !           513:         d.l = src2;                                     \
        !           514:                                                         \
        !           515:         d.l = F(d.l, s.l);                              \
        !           516:                                                         \
        !           517:         return d.l;                                     \
        !           518:     }
        !           519: 
        !           520: #define FADD(a, b) ((a) + (b))
        !           521: #define FSUB(a, b) ((a) - (b))
        !           522: VIS_HELPER(helper_fpadd, FADD)
        !           523: VIS_HELPER(helper_fpsub, FSUB)
        !           524: 
        !           525: #define VIS_CMPHELPER(name, F)                                        \
        !           526:     void name##16(void)                                           \
        !           527:     {                                                             \
        !           528:         vis64 s, d;                                               \
        !           529:                                                                   \
        !           530:         s.d = DT0;                                                \
        !           531:         d.d = DT1;                                                \
        !           532:                                                                   \
        !           533:         d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0;       \
        !           534:         d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0;      \
        !           535:         d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0;      \
        !           536:         d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0;      \
        !           537:                                                                   \
        !           538:         DT0 = d.d;                                                \
        !           539:     }                                                             \
        !           540:                                                                   \
        !           541:     void name##32(void)                                           \
        !           542:     {                                                             \
        !           543:         vis64 s, d;                                               \
        !           544:                                                                   \
        !           545:         s.d = DT0;                                                \
        !           546:         d.d = DT1;                                                \
        !           547:                                                                   \
        !           548:         d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0;       \
        !           549:         d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0;      \
        !           550:                                                                   \
        !           551:         DT0 = d.d;                                                \
        !           552:     }
        !           553: 
        !           554: #define FCMPGT(a, b) ((a) > (b))
        !           555: #define FCMPEQ(a, b) ((a) == (b))
        !           556: #define FCMPLE(a, b) ((a) <= (b))
        !           557: #define FCMPNE(a, b) ((a) != (b))
        !           558: 
        !           559: VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
        !           560: VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
        !           561: VIS_CMPHELPER(helper_fcmple, FCMPLE)
        !           562: VIS_CMPHELPER(helper_fcmpne, FCMPNE)
1.1.1.5   root      563: #endif
1.1       root      564: 
1.1.1.6 ! root      565: void helper_check_ieee_exceptions(void)
        !           566: {
        !           567:     target_ulong status;
        !           568: 
        !           569:     status = get_float_exception_flags(&env->fp_status);
        !           570:     if (status) {
        !           571:         /* Copy IEEE 754 flags into FSR */
        !           572:         if (status & float_flag_invalid)
        !           573:             env->fsr |= FSR_NVC;
        !           574:         if (status & float_flag_overflow)
        !           575:             env->fsr |= FSR_OFC;
        !           576:         if (status & float_flag_underflow)
        !           577:             env->fsr |= FSR_UFC;
        !           578:         if (status & float_flag_divbyzero)
        !           579:             env->fsr |= FSR_DZC;
        !           580:         if (status & float_flag_inexact)
        !           581:             env->fsr |= FSR_NXC;
        !           582: 
        !           583:         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
        !           584:             /* Unmasked exception, generate a trap */
        !           585:             env->fsr |= FSR_FTT_IEEE_EXCP;
        !           586:             raise_exception(TT_FP_EXCP);
        !           587:         } else {
        !           588:             /* Accumulate exceptions */
        !           589:             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
        !           590:         }
        !           591:     }
        !           592: }
        !           593: 
        !           594: void helper_clear_float_exceptions(void)
        !           595: {
        !           596:     set_float_exception_flags(0, &env->fp_status);
        !           597: }
        !           598: 
        !           599: float32 helper_fabss(float32 src)
1.1       root      600: {
1.1.1.6 ! root      601:     return float32_abs(src);
1.1       root      602: }
                    603: 
                    604: #ifdef TARGET_SPARC64
1.1.1.6 ! root      605: void helper_fabsd(void)
1.1       root      606: {
                    607:     DT0 = float64_abs(DT1);
                    608: }
1.1.1.5   root      609: 
1.1.1.6 ! root      610: void helper_fabsq(void)
1.1.1.5   root      611: {
                    612:     QT0 = float128_abs(QT1);
                    613: }
                    614: #endif
1.1       root      615: 
1.1.1.6 ! root      616: float32 helper_fsqrts(float32 src)
1.1       root      617: {
1.1.1.6 ! root      618:     return float32_sqrt(src, &env->fp_status);
1.1       root      619: }
                    620: 
1.1.1.6 ! root      621: void helper_fsqrtd(void)
1.1       root      622: {
                    623:     DT0 = float64_sqrt(DT1, &env->fp_status);
                    624: }
                    625: 
1.1.1.6 ! root      626: void helper_fsqrtq(void)
1.1.1.5   root      627: {
                    628:     QT0 = float128_sqrt(QT1, &env->fp_status);
                    629: }
                    630: 
                    631: #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
1.1.1.6 ! root      632:     void glue(helper_, name) (void)                                     \
1.1.1.3   root      633:     {                                                                   \
1.1.1.6 ! root      634:         target_ulong new_fsr;                                           \
        !           635:                                                                         \
1.1.1.3   root      636:         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
                    637:         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
                    638:         case float_relation_unordered:                                  \
1.1.1.6 ! root      639:             new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
        !           640:             if ((env->fsr & FSR_NVM) || TRAP) {                         \
        !           641:                 env->fsr |= new_fsr;                                    \
        !           642:                 env->fsr |= FSR_NVC;                                    \
        !           643:                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
        !           644:                 raise_exception(TT_FP_EXCP);                            \
        !           645:             } else {                                                    \
        !           646:                 env->fsr |= FSR_NVA;                                    \
        !           647:             }                                                           \
        !           648:             break;                                                      \
        !           649:         case float_relation_less:                                       \
        !           650:             new_fsr = FSR_FCC0 << FS;                                   \
        !           651:             break;                                                      \
        !           652:         case float_relation_greater:                                    \
        !           653:             new_fsr = FSR_FCC1 << FS;                                   \
        !           654:             break;                                                      \
        !           655:         default:                                                        \
        !           656:             new_fsr = 0;                                                \
        !           657:             break;                                                      \
        !           658:         }                                                               \
        !           659:         env->fsr |= new_fsr;                                            \
        !           660:     }
        !           661: #define GEN_FCMPS(name, size, FS, TRAP)                                 \
        !           662:     void glue(helper_, name)(float32 src1, float32 src2)                \
        !           663:     {                                                                   \
        !           664:         target_ulong new_fsr;                                           \
        !           665:                                                                         \
        !           666:         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
        !           667:         switch (glue(size, _compare) (src1, src2, &env->fp_status)) {   \
        !           668:         case float_relation_unordered:                                  \
        !           669:             new_fsr = (FSR_FCC1 | FSR_FCC0) << FS;                      \
1.1.1.5   root      670:             if ((env->fsr & FSR_NVM) || TRAP) {                         \
1.1.1.6 ! root      671:                 env->fsr |= new_fsr;                                    \
1.1.1.5   root      672:                 env->fsr |= FSR_NVC;                                    \
                    673:                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
1.1.1.3   root      674:                 raise_exception(TT_FP_EXCP);                            \
                    675:             } else {                                                    \
                    676:                 env->fsr |= FSR_NVA;                                    \
                    677:             }                                                           \
                    678:             break;                                                      \
                    679:         case float_relation_less:                                       \
1.1.1.6 ! root      680:             new_fsr = FSR_FCC0 << FS;                                   \
1.1.1.3   root      681:             break;                                                      \
                    682:         case float_relation_greater:                                    \
1.1.1.6 ! root      683:             new_fsr = FSR_FCC1 << FS;                                   \
1.1.1.3   root      684:             break;                                                      \
                    685:         default:                                                        \
1.1.1.6 ! root      686:             new_fsr = 0;                                                \
1.1.1.3   root      687:             break;                                                      \
                    688:         }                                                               \
1.1.1.6 ! root      689:         env->fsr |= new_fsr;                                            \
1.1       root      690:     }
                    691: 
1.1.1.6 ! root      692: GEN_FCMPS(fcmps, float32, 0, 0);
1.1.1.5   root      693: GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
                    694: 
1.1.1.6 ! root      695: GEN_FCMPS(fcmpes, float32, 0, 1);
1.1.1.5   root      696: GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
                    697: 
                    698: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
                    699: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
1.1       root      700: 
                    701: #ifdef TARGET_SPARC64
1.1.1.6 ! root      702: GEN_FCMPS(fcmps_fcc1, float32, 22, 0);
1.1.1.5   root      703: GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1.1.1.6 ! root      704: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
1.1       root      705: 
1.1.1.6 ! root      706: GEN_FCMPS(fcmps_fcc2, float32, 24, 0);
1.1.1.5   root      707: GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1.1.1.6 ! root      708: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
1.1       root      709: 
1.1.1.6 ! root      710: GEN_FCMPS(fcmps_fcc3, float32, 26, 0);
1.1.1.5   root      711: GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
1.1.1.6 ! root      712: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
1.1.1.5   root      713: 
1.1.1.6 ! root      714: GEN_FCMPS(fcmpes_fcc1, float32, 22, 1);
1.1.1.5   root      715: GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
1.1.1.6 ! root      716: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
1.1.1.5   root      717: 
1.1.1.6 ! root      718: GEN_FCMPS(fcmpes_fcc2, float32, 24, 1);
1.1.1.5   root      719: GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
1.1.1.6 ! root      720: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
1.1.1.5   root      721: 
1.1.1.6 ! root      722: GEN_FCMPS(fcmpes_fcc3, float32, 26, 1);
1.1.1.5   root      723: GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
                    724: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
                    725: #endif
1.1.1.6 ! root      726: #undef GEN_FCMPS
1.1.1.5   root      727: 
1.1.1.6 ! root      728: #if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
        !           729:     defined(DEBUG_MXCC)
1.1.1.5   root      730: static void dump_mxcc(CPUState *env)
1.1.1.2   root      731: {
1.1.1.5   root      732:     printf("mxccdata: %016llx %016llx %016llx %016llx\n",
1.1.1.6 ! root      733:            env->mxccdata[0], env->mxccdata[1],
        !           734:            env->mxccdata[2], env->mxccdata[3]);
1.1.1.5   root      735:     printf("mxccregs: %016llx %016llx %016llx %016llx\n"
                    736:            "          %016llx %016llx %016llx %016llx\n",
1.1.1.6 ! root      737:            env->mxccregs[0], env->mxccregs[1],
        !           738:            env->mxccregs[2], env->mxccregs[3],
        !           739:            env->mxccregs[4], env->mxccregs[5],
        !           740:            env->mxccregs[6], env->mxccregs[7]);
1.1.1.2   root      741: }
1.1.1.5   root      742: #endif
1.1.1.2   root      743: 
1.1.1.6 ! root      744: #if (defined(TARGET_SPARC64) || !defined(CONFIG_USER_ONLY)) \
        !           745:     && defined(DEBUG_ASI)
        !           746: static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
        !           747:                      uint64_t r1)
1.1.1.5   root      748: {
                    749:     switch (size)
                    750:     {
                    751:     case 1:
1.1.1.6 ! root      752:         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %02" PRIx64 "\n", txt,
        !           753:                     addr, asi, r1 & 0xff);
1.1.1.5   root      754:         break;
                    755:     case 2:
1.1.1.6 ! root      756:         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %04" PRIx64 "\n", txt,
        !           757:                     addr, asi, r1 & 0xffff);
1.1.1.5   root      758:         break;
                    759:     case 4:
1.1.1.6 ! root      760:         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %08" PRIx64 "\n", txt,
        !           761:                     addr, asi, r1 & 0xffffffff);
1.1.1.5   root      762:         break;
                    763:     case 8:
1.1.1.6 ! root      764:         DPRINTF_ASI("%s "TARGET_FMT_lx " asi 0x%02x = %016" PRIx64 "\n", txt,
        !           765:                     addr, asi, r1);
1.1.1.5   root      766:         break;
                    767:     }
1.1.1.2   root      768: }
1.1.1.5   root      769: #endif
                    770: 
1.1.1.6 ! root      771: #ifndef TARGET_SPARC64
        !           772: #ifndef CONFIG_USER_ONLY
        !           773: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1.1       root      774: {
1.1.1.6 ! root      775:     uint64_t ret = 0;
1.1.1.5   root      776: #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
1.1.1.6 ! root      777:     uint32_t last_addr = addr;
1.1.1.5   root      778: #endif
1.1       root      779: 
1.1.1.6 ! root      780:     helper_check_align(addr, size - 1);
1.1       root      781:     switch (asi) {
1.1.1.5   root      782:     case 2: /* SuperSparc MXCC registers */
1.1.1.6 ! root      783:         switch (addr) {
1.1.1.5   root      784:         case 0x01c00a00: /* MXCC control register */
1.1.1.6 ! root      785:             if (size == 8)
        !           786:                 ret = env->mxccregs[3];
        !           787:             else
        !           788:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !           789:                              size);
1.1.1.5   root      790:             break;
                    791:         case 0x01c00a04: /* MXCC control register */
                    792:             if (size == 4)
                    793:                 ret = env->mxccregs[3];
                    794:             else
1.1.1.6 ! root      795:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !           796:                              size);
1.1.1.5   root      797:             break;
                    798:         case 0x01c00c00: /* Module reset register */
                    799:             if (size == 8) {
1.1.1.6 ! root      800:                 ret = env->mxccregs[5];
1.1.1.5   root      801:                 // should we do something here?
                    802:             } else
1.1.1.6 ! root      803:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !           804:                              size);
1.1.1.5   root      805:             break;
                    806:         case 0x01c00f00: /* MBus port address register */
1.1.1.6 ! root      807:             if (size == 8)
        !           808:                 ret = env->mxccregs[7];
        !           809:             else
        !           810:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !           811:                              size);
1.1.1.5   root      812:             break;
                    813:         default:
1.1.1.6 ! root      814:             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
        !           815:                          size);
1.1.1.5   root      816:             break;
                    817:         }
1.1.1.6 ! root      818:         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
        !           819:                      "addr = %08x -> ret = %" PRIx64 ","
        !           820:                      "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
1.1.1.5   root      821: #ifdef DEBUG_MXCC
                    822:         dump_mxcc(env);
                    823: #endif
                    824:         break;
1.1       root      825:     case 3: /* MMU probe */
1.1.1.5   root      826:         {
                    827:             int mmulev;
1.1       root      828: 
1.1.1.6 ! root      829:             mmulev = (addr >> 8) & 15;
1.1.1.5   root      830:             if (mmulev > 4)
                    831:                 ret = 0;
1.1.1.6 ! root      832:             else
        !           833:                 ret = mmu_probe(env, addr, mmulev);
        !           834:             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08" PRIx64 "\n",
        !           835:                         addr, mmulev, ret);
1.1.1.5   root      836:         }
                    837:         break;
1.1       root      838:     case 4: /* read MMU regs */
1.1.1.5   root      839:         {
1.1.1.6 ! root      840:             int reg = (addr >> 8) & 0x1f;
1.1.1.5   root      841: 
                    842:             ret = env->mmuregs[reg];
                    843:             if (reg == 3) /* Fault status cleared on read */
                    844:                 env->mmuregs[3] = 0;
                    845:             else if (reg == 0x13) /* Fault status read */
                    846:                 ret = env->mmuregs[3];
                    847:             else if (reg == 0x14) /* Fault address read */
                    848:                 ret = env->mmuregs[4];
1.1.1.6 ! root      849:             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08" PRIx64 "\n", reg, ret);
1.1.1.5   root      850:         }
                    851:         break;
                    852:     case 5: // Turbosparc ITLB Diagnostic
                    853:     case 6: // Turbosparc DTLB Diagnostic
                    854:     case 7: // Turbosparc IOTLB Diagnostic
                    855:         break;
                    856:     case 9: /* Supervisor code access */
                    857:         switch(size) {
                    858:         case 1:
1.1.1.6 ! root      859:             ret = ldub_code(addr);
1.1.1.5   root      860:             break;
                    861:         case 2:
1.1.1.6 ! root      862:             ret = lduw_code(addr);
1.1.1.5   root      863:             break;
                    864:         default:
                    865:         case 4:
1.1.1.6 ! root      866:             ret = ldl_code(addr);
1.1.1.5   root      867:             break;
                    868:         case 8:
1.1.1.6 ! root      869:             ret = ldq_code(addr);
1.1.1.5   root      870:             break;
                    871:         }
                    872:         break;
                    873:     case 0xa: /* User data access */
                    874:         switch(size) {
                    875:         case 1:
1.1.1.6 ! root      876:             ret = ldub_user(addr);
1.1.1.5   root      877:             break;
                    878:         case 2:
1.1.1.6 ! root      879:             ret = lduw_user(addr);
1.1.1.5   root      880:             break;
                    881:         default:
                    882:         case 4:
1.1.1.6 ! root      883:             ret = ldl_user(addr);
1.1.1.5   root      884:             break;
                    885:         case 8:
1.1.1.6 ! root      886:             ret = ldq_user(addr);
1.1.1.5   root      887:             break;
                    888:         }
                    889:         break;
                    890:     case 0xb: /* Supervisor data access */
                    891:         switch(size) {
                    892:         case 1:
1.1.1.6 ! root      893:             ret = ldub_kernel(addr);
1.1.1.5   root      894:             break;
                    895:         case 2:
1.1.1.6 ! root      896:             ret = lduw_kernel(addr);
1.1.1.5   root      897:             break;
                    898:         default:
                    899:         case 4:
1.1.1.6 ! root      900:             ret = ldl_kernel(addr);
1.1.1.5   root      901:             break;
                    902:         case 8:
1.1.1.6 ! root      903:             ret = ldq_kernel(addr);
1.1.1.5   root      904:             break;
                    905:         }
                    906:         break;
                    907:     case 0xc: /* I-cache tag */
                    908:     case 0xd: /* I-cache data */
                    909:     case 0xe: /* D-cache tag */
                    910:     case 0xf: /* D-cache data */
                    911:         break;
                    912:     case 0x20: /* MMU passthrough */
1.1.1.2   root      913:         switch(size) {
                    914:         case 1:
1.1.1.6 ! root      915:             ret = ldub_phys(addr);
1.1.1.2   root      916:             break;
                    917:         case 2:
1.1.1.6 ! root      918:             ret = lduw_phys(addr);
1.1.1.2   root      919:             break;
                    920:         default:
                    921:         case 4:
1.1.1.6 ! root      922:             ret = ldl_phys(addr);
1.1.1.2   root      923:             break;
                    924:         case 8:
1.1.1.6 ! root      925:             ret = ldq_phys(addr);
1.1.1.5   root      926:             break;
1.1.1.2   root      927:         }
1.1.1.5   root      928:         break;
                    929:     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
                    930:         switch(size) {
                    931:         case 1:
1.1.1.6 ! root      932:             ret = ldub_phys((target_phys_addr_t)addr
1.1.1.5   root      933:                             | ((target_phys_addr_t)(asi & 0xf) << 32));
                    934:             break;
                    935:         case 2:
1.1.1.6 ! root      936:             ret = lduw_phys((target_phys_addr_t)addr
1.1.1.5   root      937:                             | ((target_phys_addr_t)(asi & 0xf) << 32));
                    938:             break;
                    939:         default:
                    940:         case 4:
1.1.1.6 ! root      941:             ret = ldl_phys((target_phys_addr_t)addr
1.1.1.5   root      942:                            | ((target_phys_addr_t)(asi & 0xf) << 32));
                    943:             break;
                    944:         case 8:
1.1.1.6 ! root      945:             ret = ldq_phys((target_phys_addr_t)addr
1.1.1.5   root      946:                            | ((target_phys_addr_t)(asi & 0xf) << 32));
                    947:             break;
                    948:         }
                    949:         break;
                    950:     case 0x30: // Turbosparc secondary cache diagnostic
                    951:     case 0x31: // Turbosparc RAM snoop
                    952:     case 0x32: // Turbosparc page table descriptor diagnostic
                    953:     case 0x39: /* data cache diagnostic register */
                    954:         ret = 0;
                    955:         break;
1.1.1.6 ! root      956:     case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
        !           957:         {
        !           958:             int reg = (addr >> 8) & 3;
        !           959: 
        !           960:             switch(reg) {
        !           961:             case 0: /* Breakpoint Value (Addr) */
        !           962:                 ret = env->mmubpregs[reg];
        !           963:                 break;
        !           964:             case 1: /* Breakpoint Mask */
        !           965:                 ret = env->mmubpregs[reg];
        !           966:                 break;
        !           967:             case 2: /* Breakpoint Control */
        !           968:                 ret = env->mmubpregs[reg];
        !           969:                 break;
        !           970:             case 3: /* Breakpoint Status */
        !           971:                 ret = env->mmubpregs[reg];
        !           972:                 env->mmubpregs[reg] = 0ULL;
        !           973:                 break;
        !           974:             }
        !           975:             DPRINTF_MMU("read breakpoint reg[%d] 0x%016llx\n", reg, ret);
        !           976:         }
        !           977:         break;
1.1.1.5   root      978:     case 8: /* User code access, XXX */
1.1       root      979:     default:
1.1.1.6 ! root      980:         do_unassigned_access(addr, 0, 0, asi, size);
1.1.1.5   root      981:         ret = 0;
                    982:         break;
1.1       root      983:     }
1.1.1.5   root      984:     if (sign) {
                    985:         switch(size) {
                    986:         case 1:
1.1.1.6 ! root      987:             ret = (int8_t) ret;
1.1.1.5   root      988:             break;
                    989:         case 2:
1.1.1.6 ! root      990:             ret = (int16_t) ret;
        !           991:             break;
        !           992:         case 4:
        !           993:             ret = (int32_t) ret;
1.1.1.5   root      994:             break;
                    995:         default:
                    996:             break;
                    997:         }
                    998:     }
                    999: #ifdef DEBUG_ASI
1.1.1.6 ! root     1000:     dump_asi("read ", last_addr, asi, size, ret);
1.1.1.5   root     1001: #endif
1.1.1.6 ! root     1002:     return ret;
1.1       root     1003: }
                   1004: 
1.1.1.6 ! root     1005: void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
1.1       root     1006: {
1.1.1.6 ! root     1007:     helper_check_align(addr, size - 1);
1.1       root     1008:     switch(asi) {
1.1.1.5   root     1009:     case 2: /* SuperSparc MXCC registers */
1.1.1.6 ! root     1010:         switch (addr) {
1.1.1.5   root     1011:         case 0x01c00000: /* MXCC stream data register 0 */
                   1012:             if (size == 8)
1.1.1.6 ! root     1013:                 env->mxccdata[0] = val;
1.1.1.5   root     1014:             else
1.1.1.6 ! root     1015:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1016:                              size);
1.1.1.5   root     1017:             break;
                   1018:         case 0x01c00008: /* MXCC stream data register 1 */
                   1019:             if (size == 8)
1.1.1.6 ! root     1020:                 env->mxccdata[1] = val;
1.1.1.5   root     1021:             else
1.1.1.6 ! root     1022:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1023:                              size);
1.1.1.5   root     1024:             break;
                   1025:         case 0x01c00010: /* MXCC stream data register 2 */
                   1026:             if (size == 8)
1.1.1.6 ! root     1027:                 env->mxccdata[2] = val;
1.1.1.5   root     1028:             else
1.1.1.6 ! root     1029:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1030:                              size);
1.1.1.5   root     1031:             break;
                   1032:         case 0x01c00018: /* MXCC stream data register 3 */
                   1033:             if (size == 8)
1.1.1.6 ! root     1034:                 env->mxccdata[3] = val;
1.1.1.5   root     1035:             else
1.1.1.6 ! root     1036:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1037:                              size);
1.1.1.5   root     1038:             break;
                   1039:         case 0x01c00100: /* MXCC stream source */
                   1040:             if (size == 8)
1.1.1.6 ! root     1041:                 env->mxccregs[0] = val;
1.1.1.5   root     1042:             else
1.1.1.6 ! root     1043:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1044:                              size);
        !          1045:             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
        !          1046:                                         0);
        !          1047:             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
        !          1048:                                         8);
        !          1049:             env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
        !          1050:                                         16);
        !          1051:             env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
        !          1052:                                         24);
1.1.1.5   root     1053:             break;
                   1054:         case 0x01c00200: /* MXCC stream destination */
                   1055:             if (size == 8)
1.1.1.6 ! root     1056:                 env->mxccregs[1] = val;
1.1.1.5   root     1057:             else
1.1.1.6 ! root     1058:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1059:                              size);
        !          1060:             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,
        !          1061:                      env->mxccdata[0]);
        !          1062:             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,
        !          1063:                      env->mxccdata[1]);
        !          1064:             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
        !          1065:                      env->mxccdata[2]);
        !          1066:             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
        !          1067:                      env->mxccdata[3]);
1.1.1.5   root     1068:             break;
                   1069:         case 0x01c00a00: /* MXCC control register */
                   1070:             if (size == 8)
1.1.1.6 ! root     1071:                 env->mxccregs[3] = val;
1.1.1.5   root     1072:             else
1.1.1.6 ! root     1073:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1074:                              size);
1.1.1.5   root     1075:             break;
                   1076:         case 0x01c00a04: /* MXCC control register */
                   1077:             if (size == 4)
1.1.1.6 ! root     1078:                 env->mxccregs[3] = (env->mxccregs[3] & 0xffffffff00000000ULL)
        !          1079:                     | val;
1.1.1.5   root     1080:             else
1.1.1.6 ! root     1081:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1082:                              size);
1.1.1.5   root     1083:             break;
                   1084:         case 0x01c00e00: /* MXCC error register  */
                   1085:             // writing a 1 bit clears the error
                   1086:             if (size == 8)
1.1.1.6 ! root     1087:                 env->mxccregs[6] &= ~val;
1.1.1.5   root     1088:             else
1.1.1.6 ! root     1089:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1090:                              size);
1.1.1.5   root     1091:             break;
                   1092:         case 0x01c00f00: /* MBus port address register */
                   1093:             if (size == 8)
1.1.1.6 ! root     1094:                 env->mxccregs[7] = val;
1.1.1.5   root     1095:             else
1.1.1.6 ! root     1096:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,
        !          1097:                              size);
1.1.1.5   root     1098:             break;
                   1099:         default:
1.1.1.6 ! root     1100:             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,
        !          1101:                          size);
1.1.1.5   root     1102:             break;
                   1103:         }
1.1.1.6 ! root     1104:         DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
        !          1105:                      asi, size, addr, val);
1.1.1.5   root     1106: #ifdef DEBUG_MXCC
                   1107:         dump_mxcc(env);
                   1108: #endif
                   1109:         break;
1.1       root     1110:     case 3: /* MMU flush */
1.1.1.5   root     1111:         {
                   1112:             int mmulev;
1.1       root     1113: 
1.1.1.6 ! root     1114:             mmulev = (addr >> 8) & 15;
1.1.1.5   root     1115:             DPRINTF_MMU("mmu flush level %d\n", mmulev);
                   1116:             switch (mmulev) {
                   1117:             case 0: // flush page
1.1.1.6 ! root     1118:                 tlb_flush_page(env, addr & 0xfffff000);
1.1.1.5   root     1119:                 break;
                   1120:             case 1: // flush segment (256k)
                   1121:             case 2: // flush region (16M)
                   1122:             case 3: // flush context (4G)
                   1123:             case 4: // flush entire
                   1124:                 tlb_flush(env, 1);
                   1125:                 break;
                   1126:             default:
                   1127:                 break;
                   1128:             }
1.1       root     1129: #ifdef DEBUG_MMU
1.1.1.5   root     1130:             dump_mmu(env);
1.1       root     1131: #endif
1.1.1.5   root     1132:         }
                   1133:         break;
1.1       root     1134:     case 4: /* write MMU regs */
1.1.1.5   root     1135:         {
1.1.1.6 ! root     1136:             int reg = (addr >> 8) & 0x1f;
1.1.1.5   root     1137:             uint32_t oldreg;
                   1138: 
                   1139:             oldreg = env->mmuregs[reg];
1.1       root     1140:             switch(reg) {
1.1.1.6 ! root     1141:             case 0: // Control Register
1.1.1.5   root     1142:                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
1.1.1.6 ! root     1143:                                     (val & 0x00ffffff);
1.1.1.5   root     1144:                 // Mappings generated during no-fault mode or MMU
                   1145:                 // disabled mode are invalid in normal mode
1.1.1.6 ! root     1146:                 if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
        !          1147:                     (env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm)))
1.1       root     1148:                     tlb_flush(env, 1);
                   1149:                 break;
1.1.1.6 ! root     1150:             case 1: // Context Table Pointer Register
        !          1151:                 env->mmuregs[reg] = val & env->def->mmu_ctpr_mask;
        !          1152:                 break;
        !          1153:             case 2: // Context Register
        !          1154:                 env->mmuregs[reg] = val & env->def->mmu_cxr_mask;
1.1       root     1155:                 if (oldreg != env->mmuregs[reg]) {
                   1156:                     /* we flush when the MMU context changes because
                   1157:                        QEMU has no MMU context support */
                   1158:                     tlb_flush(env, 1);
                   1159:                 }
                   1160:                 break;
1.1.1.6 ! root     1161:             case 3: // Synchronous Fault Status Register with Clear
        !          1162:             case 4: // Synchronous Fault Address Register
1.1       root     1163:                 break;
1.1.1.6 ! root     1164:             case 0x10: // TLB Replacement Control Register
        !          1165:                 env->mmuregs[reg] = val & env->def->mmu_trcr_mask;
1.1.1.5   root     1166:                 break;
1.1.1.6 ! root     1167:             case 0x13: // Synchronous Fault Status Register with Read and Clear
        !          1168:                 env->mmuregs[3] = val & env->def->mmu_sfsr_mask;
        !          1169:                 break;
        !          1170:             case 0x14: // Synchronous Fault Address Register
        !          1171:                 env->mmuregs[4] = val;
1.1.1.5   root     1172:                 break;
1.1       root     1173:             default:
1.1.1.6 ! root     1174:                 env->mmuregs[reg] = val;
1.1       root     1175:                 break;
                   1176:             }
                   1177:             if (oldreg != env->mmuregs[reg]) {
1.1.1.6 ! root     1178:                 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",
        !          1179:                             reg, oldreg, env->mmuregs[reg]);
1.1       root     1180:             }
1.1.1.5   root     1181: #ifdef DEBUG_MMU
                   1182:             dump_mmu(env);
1.1       root     1183: #endif
1.1.1.5   root     1184:         }
                   1185:         break;
                   1186:     case 5: // Turbosparc ITLB Diagnostic
                   1187:     case 6: // Turbosparc DTLB Diagnostic
                   1188:     case 7: // Turbosparc IOTLB Diagnostic
                   1189:         break;
                   1190:     case 0xa: /* User data access */
                   1191:         switch(size) {
                   1192:         case 1:
1.1.1.6 ! root     1193:             stb_user(addr, val);
1.1.1.5   root     1194:             break;
                   1195:         case 2:
1.1.1.6 ! root     1196:             stw_user(addr, val);
1.1.1.5   root     1197:             break;
                   1198:         default:
                   1199:         case 4:
1.1.1.6 ! root     1200:             stl_user(addr, val);
1.1.1.5   root     1201:             break;
                   1202:         case 8:
1.1.1.6 ! root     1203:             stq_user(addr, val);
1.1.1.5   root     1204:             break;
                   1205:         }
                   1206:         break;
                   1207:     case 0xb: /* Supervisor data access */
                   1208:         switch(size) {
                   1209:         case 1:
1.1.1.6 ! root     1210:             stb_kernel(addr, val);
1.1.1.5   root     1211:             break;
                   1212:         case 2:
1.1.1.6 ! root     1213:             stw_kernel(addr, val);
1.1.1.5   root     1214:             break;
                   1215:         default:
                   1216:         case 4:
1.1.1.6 ! root     1217:             stl_kernel(addr, val);
1.1.1.5   root     1218:             break;
                   1219:         case 8:
1.1.1.6 ! root     1220:             stq_kernel(addr, val);
1.1.1.5   root     1221:             break;
                   1222:         }
                   1223:         break;
                   1224:     case 0xc: /* I-cache tag */
                   1225:     case 0xd: /* I-cache data */
                   1226:     case 0xe: /* D-cache tag */
                   1227:     case 0xf: /* D-cache data */
                   1228:     case 0x10: /* I/D-cache flush page */
                   1229:     case 0x11: /* I/D-cache flush segment */
                   1230:     case 0x12: /* I/D-cache flush region */
                   1231:     case 0x13: /* I/D-cache flush context */
                   1232:     case 0x14: /* I/D-cache flush user */
                   1233:         break;
1.1       root     1234:     case 0x17: /* Block copy, sta access */
1.1.1.5   root     1235:         {
1.1.1.6 ! root     1236:             // val = src
        !          1237:             // addr = dst
1.1.1.5   root     1238:             // copy 32 bytes
                   1239:             unsigned int i;
1.1.1.6 ! root     1240:             uint32_t src = val & ~3, dst = addr & ~3, temp;
1.1.1.5   root     1241: 
                   1242:             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
                   1243:                 temp = ldl_kernel(src);
                   1244:                 stl_kernel(dst, temp);
                   1245:             }
                   1246:         }
                   1247:         break;
1.1       root     1248:     case 0x1f: /* Block fill, stda access */
1.1.1.5   root     1249:         {
1.1.1.6 ! root     1250:             // addr = dst
        !          1251:             // fill 32 bytes with val
1.1.1.5   root     1252:             unsigned int i;
1.1.1.6 ! root     1253:             uint32_t dst = addr & 7;
1.1.1.5   root     1254: 
                   1255:             for (i = 0; i < 32; i += 8, dst += 8)
                   1256:                 stq_kernel(dst, val);
                   1257:         }
                   1258:         break;
                   1259:     case 0x20: /* MMU passthrough */
                   1260:         {
                   1261:             switch(size) {
                   1262:             case 1:
1.1.1.6 ! root     1263:                 stb_phys(addr, val);
1.1.1.5   root     1264:                 break;
                   1265:             case 2:
1.1.1.6 ! root     1266:                 stw_phys(addr, val);
1.1.1.5   root     1267:                 break;
                   1268:             case 4:
                   1269:             default:
1.1.1.6 ! root     1270:                 stl_phys(addr, val);
1.1.1.5   root     1271:                 break;
                   1272:             case 8:
1.1.1.6 ! root     1273:                 stq_phys(addr, val);
1.1.1.5   root     1274:                 break;
                   1275:             }
                   1276:         }
                   1277:         break;
                   1278:     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
                   1279:         {
                   1280:             switch(size) {
                   1281:             case 1:
1.1.1.6 ! root     1282:                 stb_phys((target_phys_addr_t)addr
        !          1283:                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5   root     1284:                 break;
                   1285:             case 2:
1.1.1.6 ! root     1286:                 stw_phys((target_phys_addr_t)addr
        !          1287:                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5   root     1288:                 break;
                   1289:             case 4:
                   1290:             default:
1.1.1.6 ! root     1291:                 stl_phys((target_phys_addr_t)addr
        !          1292:                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5   root     1293:                 break;
                   1294:             case 8:
1.1.1.6 ! root     1295:                 stq_phys((target_phys_addr_t)addr
        !          1296:                          | ((target_phys_addr_t)(asi & 0xf) << 32), val);
1.1.1.5   root     1297:                 break;
                   1298:             }
                   1299:         }
                   1300:         break;
                   1301:     case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
                   1302:     case 0x31: // store buffer data, Ross RT620 I-cache flush or
                   1303:                // Turbosparc snoop RAM
1.1.1.6 ! root     1304:     case 0x32: // store buffer control or Turbosparc page table
        !          1305:                // descriptor diagnostic
1.1.1.5   root     1306:     case 0x36: /* I-cache flash clear */
                   1307:     case 0x37: /* D-cache flash clear */
                   1308:     case 0x4c: /* breakpoint action */
                   1309:         break;
1.1.1.6 ! root     1310:     case 0x38: /* SuperSPARC MMU Breakpoint Control Registers*/
        !          1311:         {
        !          1312:             int reg = (addr >> 8) & 3;
        !          1313: 
        !          1314:             switch(reg) {
        !          1315:             case 0: /* Breakpoint Value (Addr) */
        !          1316:                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
        !          1317:                 break;
        !          1318:             case 1: /* Breakpoint Mask */
        !          1319:                 env->mmubpregs[reg] = (val & 0xfffffffffULL);
        !          1320:                 break;
        !          1321:             case 2: /* Breakpoint Control */
        !          1322:                 env->mmubpregs[reg] = (val & 0x7fULL);
        !          1323:                 break;
        !          1324:             case 3: /* Breakpoint Status */
        !          1325:                 env->mmubpregs[reg] = (val & 0xfULL);
        !          1326:                 break;
        !          1327:             }
        !          1328:             DPRINTF_MMU("write breakpoint reg[%d] 0x%016llx\n", reg,
        !          1329:                         env->mmuregs[reg]);
        !          1330:         }
        !          1331:         break;
1.1.1.5   root     1332:     case 8: /* User code access, XXX */
                   1333:     case 9: /* Supervisor code access, XXX */
                   1334:     default:
1.1.1.6 ! root     1335:         do_unassigned_access(addr, 1, 0, asi, size);
1.1.1.5   root     1336:         break;
                   1337:     }
                   1338: #ifdef DEBUG_ASI
1.1.1.6 ! root     1339:     dump_asi("write", addr, asi, size, val);
1.1.1.5   root     1340: #endif
                   1341: }
                   1342: 
                   1343: #endif /* CONFIG_USER_ONLY */
                   1344: #else /* TARGET_SPARC64 */
                   1345: 
                   1346: #ifdef CONFIG_USER_ONLY
1.1.1.6 ! root     1347: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1.1.1.5   root     1348: {
                   1349:     uint64_t ret = 0;
1.1.1.6 ! root     1350: #if defined(DEBUG_ASI)
        !          1351:     target_ulong last_addr = addr;
        !          1352: #endif
1.1.1.5   root     1353: 
                   1354:     if (asi < 0x80)
                   1355:         raise_exception(TT_PRIV_ACT);
                   1356: 
1.1.1.6 ! root     1357:     helper_check_align(addr, size - 1);
        !          1358:     address_mask(env, &addr);
        !          1359: 
1.1.1.5   root     1360:     switch (asi) {
                   1361:     case 0x82: // Primary no-fault
                   1362:     case 0x8a: // Primary no-fault LE
1.1.1.6 ! root     1363:         if (page_check_range(addr, size, PAGE_READ) == -1) {
        !          1364: #ifdef DEBUG_ASI
        !          1365:             dump_asi("read ", last_addr, asi, size, ret);
        !          1366: #endif
        !          1367:             return 0;
        !          1368:         }
        !          1369:         // Fall through
        !          1370:     case 0x80: // Primary
        !          1371:     case 0x88: // Primary LE
1.1.1.5   root     1372:         {
                   1373:             switch(size) {
                   1374:             case 1:
1.1.1.6 ! root     1375:                 ret = ldub_raw(addr);
1.1.1.5   root     1376:                 break;
                   1377:             case 2:
1.1.1.6 ! root     1378:                 ret = lduw_raw(addr);
1.1.1.5   root     1379:                 break;
                   1380:             case 4:
1.1.1.6 ! root     1381:                 ret = ldl_raw(addr);
1.1.1.5   root     1382:                 break;
                   1383:             default:
                   1384:             case 8:
1.1.1.6 ! root     1385:                 ret = ldq_raw(addr);
1.1.1.5   root     1386:                 break;
                   1387:             }
                   1388:         }
                   1389:         break;
                   1390:     case 0x83: // Secondary no-fault
                   1391:     case 0x8b: // Secondary no-fault LE
1.1.1.6 ! root     1392:         if (page_check_range(addr, size, PAGE_READ) == -1) {
        !          1393: #ifdef DEBUG_ASI
        !          1394:             dump_asi("read ", last_addr, asi, size, ret);
        !          1395: #endif
        !          1396:             return 0;
        !          1397:         }
        !          1398:         // Fall through
        !          1399:     case 0x81: // Secondary
        !          1400:     case 0x89: // Secondary LE
1.1.1.5   root     1401:         // XXX
                   1402:         break;
                   1403:     default:
                   1404:         break;
                   1405:     }
                   1406: 
                   1407:     /* Convert from little endian */
                   1408:     switch (asi) {
                   1409:     case 0x88: // Primary LE
                   1410:     case 0x89: // Secondary LE
                   1411:     case 0x8a: // Primary no-fault LE
                   1412:     case 0x8b: // Secondary no-fault LE
                   1413:         switch(size) {
                   1414:         case 2:
                   1415:             ret = bswap16(ret);
                   1416:             break;
                   1417:         case 4:
                   1418:             ret = bswap32(ret);
                   1419:             break;
                   1420:         case 8:
                   1421:             ret = bswap64(ret);
                   1422:             break;
                   1423:         default:
                   1424:             break;
                   1425:         }
                   1426:     default:
                   1427:         break;
                   1428:     }
                   1429: 
                   1430:     /* Convert to signed number */
                   1431:     if (sign) {
                   1432:         switch(size) {
                   1433:         case 1:
                   1434:             ret = (int8_t) ret;
                   1435:             break;
                   1436:         case 2:
                   1437:             ret = (int16_t) ret;
                   1438:             break;
                   1439:         case 4:
                   1440:             ret = (int32_t) ret;
                   1441:             break;
                   1442:         default:
                   1443:             break;
                   1444:         }
                   1445:     }
1.1.1.6 ! root     1446: #ifdef DEBUG_ASI
        !          1447:     dump_asi("read ", last_addr, asi, size, ret);
        !          1448: #endif
        !          1449:     return ret;
1.1.1.5   root     1450: }
                   1451: 
1.1.1.6 ! root     1452: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1.1.1.5   root     1453: {
1.1.1.6 ! root     1454: #ifdef DEBUG_ASI
        !          1455:     dump_asi("write", addr, asi, size, val);
        !          1456: #endif
1.1.1.5   root     1457:     if (asi < 0x80)
                   1458:         raise_exception(TT_PRIV_ACT);
                   1459: 
1.1.1.6 ! root     1460:     helper_check_align(addr, size - 1);
        !          1461:     address_mask(env, &addr);
        !          1462: 
1.1.1.5   root     1463:     /* Convert to little endian */
                   1464:     switch (asi) {
                   1465:     case 0x88: // Primary LE
                   1466:     case 0x89: // Secondary LE
                   1467:         switch(size) {
                   1468:         case 2:
1.1.1.6 ! root     1469:             addr = bswap16(addr);
1.1.1.5   root     1470:             break;
                   1471:         case 4:
1.1.1.6 ! root     1472:             addr = bswap32(addr);
1.1.1.5   root     1473:             break;
                   1474:         case 8:
1.1.1.6 ! root     1475:             addr = bswap64(addr);
1.1.1.5   root     1476:             break;
                   1477:         default:
                   1478:             break;
                   1479:         }
                   1480:     default:
                   1481:         break;
                   1482:     }
                   1483: 
                   1484:     switch(asi) {
                   1485:     case 0x80: // Primary
                   1486:     case 0x88: // Primary LE
                   1487:         {
1.1.1.2   root     1488:             switch(size) {
                   1489:             case 1:
1.1.1.6 ! root     1490:                 stb_raw(addr, val);
1.1.1.2   root     1491:                 break;
                   1492:             case 2:
1.1.1.6 ! root     1493:                 stw_raw(addr, val);
1.1.1.2   root     1494:                 break;
                   1495:             case 4:
1.1.1.6 ! root     1496:                 stl_raw(addr, val);
1.1.1.2   root     1497:                 break;
                   1498:             case 8:
1.1.1.5   root     1499:             default:
1.1.1.6 ! root     1500:                 stq_raw(addr, val);
1.1.1.2   root     1501:                 break;
                   1502:             }
1.1.1.5   root     1503:         }
                   1504:         break;
                   1505:     case 0x81: // Secondary
                   1506:     case 0x89: // Secondary LE
                   1507:         // XXX
                   1508:         return;
                   1509: 
                   1510:     case 0x82: // Primary no-fault, RO
                   1511:     case 0x83: // Secondary no-fault, RO
                   1512:     case 0x8a: // Primary no-fault LE, RO
                   1513:     case 0x8b: // Secondary no-fault LE, RO
1.1       root     1514:     default:
1.1.1.6 ! root     1515:         do_unassigned_access(addr, 1, 0, 1, size);
1.1.1.5   root     1516:         return;
1.1       root     1517:     }
                   1518: }
                   1519: 
1.1.1.5   root     1520: #else /* CONFIG_USER_ONLY */
1.1       root     1521: 
1.1.1.6 ! root     1522: uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
1.1       root     1523: {
                   1524:     uint64_t ret = 0;
1.1.1.6 ! root     1525: #if defined(DEBUG_ASI)
        !          1526:     target_ulong last_addr = addr;
        !          1527: #endif
1.1       root     1528: 
1.1.1.5   root     1529:     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1.1.1.6 ! root     1530:         || ((env->def->features & CPU_FEATURE_HYPV)
        !          1531:             && asi >= 0x30 && asi < 0x80
        !          1532:             && !(env->hpstate & HS_PRIV)))
1.1.1.5   root     1533:         raise_exception(TT_PRIV_ACT);
1.1       root     1534: 
1.1.1.6 ! root     1535:     helper_check_align(addr, size - 1);
1.1       root     1536:     switch (asi) {
1.1.1.6 ! root     1537:     case 0x82: // Primary no-fault
        !          1538:     case 0x8a: // Primary no-fault LE
        !          1539:         if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
        !          1540: #ifdef DEBUG_ASI
        !          1541:             dump_asi("read ", last_addr, asi, size, ret);
        !          1542: #endif
        !          1543:             return 0;
        !          1544:         }
        !          1545:         // Fall through
1.1.1.5   root     1546:     case 0x10: // As if user primary
                   1547:     case 0x18: // As if user primary LE
                   1548:     case 0x80: // Primary
                   1549:     case 0x88: // Primary LE
1.1.1.6 ! root     1550:     case 0xe2: // UA2007 Primary block init
        !          1551:     case 0xe3: // UA2007 Secondary block init
1.1.1.5   root     1552:         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1.1.1.6 ! root     1553:             if ((env->def->features & CPU_FEATURE_HYPV)
        !          1554:                 && env->hpstate & HS_PRIV) {
1.1.1.5   root     1555:                 switch(size) {
                   1556:                 case 1:
1.1.1.6 ! root     1557:                     ret = ldub_hypv(addr);
1.1.1.5   root     1558:                     break;
                   1559:                 case 2:
1.1.1.6 ! root     1560:                     ret = lduw_hypv(addr);
1.1.1.5   root     1561:                     break;
                   1562:                 case 4:
1.1.1.6 ! root     1563:                     ret = ldl_hypv(addr);
1.1.1.5   root     1564:                     break;
                   1565:                 default:
                   1566:                 case 8:
1.1.1.6 ! root     1567:                     ret = ldq_hypv(addr);
1.1.1.5   root     1568:                     break;
                   1569:                 }
                   1570:             } else {
                   1571:                 switch(size) {
                   1572:                 case 1:
1.1.1.6 ! root     1573:                     ret = ldub_kernel(addr);
1.1.1.5   root     1574:                     break;
                   1575:                 case 2:
1.1.1.6 ! root     1576:                     ret = lduw_kernel(addr);
1.1.1.5   root     1577:                     break;
                   1578:                 case 4:
1.1.1.6 ! root     1579:                     ret = ldl_kernel(addr);
1.1.1.5   root     1580:                     break;
                   1581:                 default:
                   1582:                 case 8:
1.1.1.6 ! root     1583:                     ret = ldq_kernel(addr);
1.1.1.5   root     1584:                     break;
                   1585:                 }
                   1586:             }
                   1587:         } else {
                   1588:             switch(size) {
                   1589:             case 1:
1.1.1.6 ! root     1590:                 ret = ldub_user(addr);
1.1.1.5   root     1591:                 break;
                   1592:             case 2:
1.1.1.6 ! root     1593:                 ret = lduw_user(addr);
1.1.1.5   root     1594:                 break;
                   1595:             case 4:
1.1.1.6 ! root     1596:                 ret = ldl_user(addr);
1.1.1.5   root     1597:                 break;
                   1598:             default:
                   1599:             case 8:
1.1.1.6 ! root     1600:                 ret = ldq_user(addr);
1.1.1.5   root     1601:                 break;
                   1602:             }
                   1603:         }
                   1604:         break;
1.1       root     1605:     case 0x14: // Bypass
                   1606:     case 0x15: // Bypass, non-cacheable
1.1.1.5   root     1607:     case 0x1c: // Bypass LE
                   1608:     case 0x1d: // Bypass, non-cacheable LE
                   1609:         {
1.1.1.2   root     1610:             switch(size) {
                   1611:             case 1:
1.1.1.6 ! root     1612:                 ret = ldub_phys(addr);
1.1.1.2   root     1613:                 break;
                   1614:             case 2:
1.1.1.6 ! root     1615:                 ret = lduw_phys(addr);
1.1.1.2   root     1616:                 break;
                   1617:             case 4:
1.1.1.6 ! root     1618:                 ret = ldl_phys(addr);
1.1.1.2   root     1619:                 break;
                   1620:             default:
                   1621:             case 8:
1.1.1.6 ! root     1622:                 ret = ldq_phys(addr);
1.1.1.2   root     1623:                 break;
                   1624:             }
1.1.1.5   root     1625:             break;
                   1626:         }
1.1.1.6 ! root     1627:     case 0x24: // Nucleus quad LDD 128 bit atomic
        !          1628:     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
        !          1629:         //  Only ldda allowed
        !          1630:         raise_exception(TT_ILL_INSN);
        !          1631:         return 0;
        !          1632:     case 0x83: // Secondary no-fault
        !          1633:     case 0x8b: // Secondary no-fault LE
        !          1634:         if (cpu_get_phys_page_debug(env, addr) == -1ULL) {
        !          1635: #ifdef DEBUG_ASI
        !          1636:             dump_asi("read ", last_addr, asi, size, ret);
        !          1637: #endif
        !          1638:             return 0;
        !          1639:         }
        !          1640:         // Fall through
1.1       root     1641:     case 0x04: // Nucleus
                   1642:     case 0x0c: // Nucleus Little Endian (LE)
                   1643:     case 0x11: // As if user secondary
                   1644:     case 0x19: // As if user secondary LE
                   1645:     case 0x4a: // UPA config
1.1.1.5   root     1646:     case 0x81: // Secondary
1.1       root     1647:     case 0x89: // Secondary LE
1.1.1.5   root     1648:         // XXX
                   1649:         break;
1.1       root     1650:     case 0x45: // LSU
1.1.1.5   root     1651:         ret = env->lsu;
                   1652:         break;
1.1       root     1653:     case 0x50: // I-MMU regs
1.1.1.5   root     1654:         {
1.1.1.6 ! root     1655:             int reg = (addr >> 3) & 0xf;
1.1       root     1656: 
1.1.1.5   root     1657:             ret = env->immuregs[reg];
                   1658:             break;
                   1659:         }
1.1       root     1660:     case 0x51: // I-MMU 8k TSB pointer
                   1661:     case 0x52: // I-MMU 64k TSB pointer
1.1.1.5   root     1662:         // XXX
                   1663:         break;
1.1.1.6 ! root     1664:     case 0x55: // I-MMU data access
        !          1665:         {
        !          1666:             int reg = (addr >> 3) & 0x3f;
        !          1667: 
        !          1668:             ret = env->itlb_tte[reg];
        !          1669:             break;
        !          1670:         }
1.1       root     1671:     case 0x56: // I-MMU tag read
1.1.1.5   root     1672:         {
1.1.1.6 ! root     1673:             int reg = (addr >> 3) & 0x3f;
1.1.1.5   root     1674: 
1.1.1.6 ! root     1675:             ret = env->itlb_tag[reg];
1.1.1.5   root     1676:             break;
                   1677:         }
1.1       root     1678:     case 0x58: // D-MMU regs
1.1.1.5   root     1679:         {
1.1.1.6 ! root     1680:             int reg = (addr >> 3) & 0xf;
1.1       root     1681: 
1.1.1.5   root     1682:             ret = env->dmmuregs[reg];
                   1683:             break;
                   1684:         }
1.1.1.6 ! root     1685:     case 0x5d: // D-MMU data access
        !          1686:         {
        !          1687:             int reg = (addr >> 3) & 0x3f;
        !          1688: 
        !          1689:             ret = env->dtlb_tte[reg];
        !          1690:             break;
        !          1691:         }
1.1       root     1692:     case 0x5e: // D-MMU tag read
1.1.1.5   root     1693:         {
1.1.1.6 ! root     1694:             int reg = (addr >> 3) & 0x3f;
1.1.1.5   root     1695: 
1.1.1.6 ! root     1696:             ret = env->dtlb_tag[reg];
1.1.1.5   root     1697:             break;
                   1698:         }
1.1.1.6 ! root     1699:     case 0x46: // D-cache data
        !          1700:     case 0x47: // D-cache tag access
        !          1701:     case 0x4b: // E-cache error enable
        !          1702:     case 0x4c: // E-cache asynchronous fault status
        !          1703:     case 0x4d: // E-cache asynchronous fault address
        !          1704:     case 0x4e: // E-cache tag data
        !          1705:     case 0x66: // I-cache instruction access
        !          1706:     case 0x67: // I-cache tag access
        !          1707:     case 0x6e: // I-cache predecode
        !          1708:     case 0x6f: // I-cache LRU etc.
        !          1709:     case 0x76: // E-cache tag
        !          1710:     case 0x7e: // E-cache tag
        !          1711:         break;
1.1       root     1712:     case 0x59: // D-MMU 8k TSB pointer
                   1713:     case 0x5a: // D-MMU 64k TSB pointer
                   1714:     case 0x5b: // D-MMU data pointer
                   1715:     case 0x48: // Interrupt dispatch, RO
                   1716:     case 0x49: // Interrupt data receive
                   1717:     case 0x7f: // Incoming interrupt vector, RO
1.1.1.5   root     1718:         // XXX
                   1719:         break;
1.1       root     1720:     case 0x54: // I-MMU data in, WO
                   1721:     case 0x57: // I-MMU demap, WO
                   1722:     case 0x5c: // D-MMU data in, WO
                   1723:     case 0x5f: // D-MMU demap, WO
                   1724:     case 0x77: // Interrupt vector, WO
                   1725:     default:
1.1.1.6 ! root     1726:         do_unassigned_access(addr, 0, 0, 1, size);
1.1.1.5   root     1727:         ret = 0;
                   1728:         break;
                   1729:     }
                   1730: 
                   1731:     /* Convert from little endian */
                   1732:     switch (asi) {
                   1733:     case 0x0c: // Nucleus Little Endian (LE)
                   1734:     case 0x18: // As if user primary LE
                   1735:     case 0x19: // As if user secondary LE
                   1736:     case 0x1c: // Bypass LE
                   1737:     case 0x1d: // Bypass, non-cacheable LE
                   1738:     case 0x88: // Primary LE
                   1739:     case 0x89: // Secondary LE
                   1740:     case 0x8a: // Primary no-fault LE
                   1741:     case 0x8b: // Secondary no-fault LE
                   1742:         switch(size) {
                   1743:         case 2:
                   1744:             ret = bswap16(ret);
                   1745:             break;
                   1746:         case 4:
                   1747:             ret = bswap32(ret);
                   1748:             break;
                   1749:         case 8:
                   1750:             ret = bswap64(ret);
                   1751:             break;
                   1752:         default:
                   1753:             break;
                   1754:         }
                   1755:     default:
                   1756:         break;
                   1757:     }
                   1758: 
                   1759:     /* Convert to signed number */
                   1760:     if (sign) {
                   1761:         switch(size) {
                   1762:         case 1:
                   1763:             ret = (int8_t) ret;
                   1764:             break;
                   1765:         case 2:
                   1766:             ret = (int16_t) ret;
                   1767:             break;
                   1768:         case 4:
                   1769:             ret = (int32_t) ret;
                   1770:             break;
                   1771:         default:
                   1772:             break;
                   1773:         }
1.1       root     1774:     }
1.1.1.6 ! root     1775: #ifdef DEBUG_ASI
        !          1776:     dump_asi("read ", last_addr, asi, size, ret);
        !          1777: #endif
        !          1778:     return ret;
1.1       root     1779: }
                   1780: 
1.1.1.6 ! root     1781: void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
1.1       root     1782: {
1.1.1.6 ! root     1783: #ifdef DEBUG_ASI
        !          1784:     dump_asi("write", addr, asi, size, val);
        !          1785: #endif
1.1.1.5   root     1786:     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
1.1.1.6 ! root     1787:         || ((env->def->features & CPU_FEATURE_HYPV)
        !          1788:             && asi >= 0x30 && asi < 0x80
        !          1789:             && !(env->hpstate & HS_PRIV)))
1.1.1.5   root     1790:         raise_exception(TT_PRIV_ACT);
                   1791: 
1.1.1.6 ! root     1792:     helper_check_align(addr, size - 1);
1.1.1.5   root     1793:     /* Convert to little endian */
                   1794:     switch (asi) {
                   1795:     case 0x0c: // Nucleus Little Endian (LE)
                   1796:     case 0x18: // As if user primary LE
                   1797:     case 0x19: // As if user secondary LE
                   1798:     case 0x1c: // Bypass LE
                   1799:     case 0x1d: // Bypass, non-cacheable LE
                   1800:     case 0x88: // Primary LE
                   1801:     case 0x89: // Secondary LE
                   1802:         switch(size) {
                   1803:         case 2:
1.1.1.6 ! root     1804:             addr = bswap16(addr);
1.1.1.5   root     1805:             break;
                   1806:         case 4:
1.1.1.6 ! root     1807:             addr = bswap32(addr);
1.1.1.5   root     1808:             break;
                   1809:         case 8:
1.1.1.6 ! root     1810:             addr = bswap64(addr);
1.1.1.5   root     1811:             break;
                   1812:         default:
                   1813:             break;
                   1814:         }
                   1815:     default:
                   1816:         break;
                   1817:     }
1.1       root     1818: 
                   1819:     switch(asi) {
1.1.1.5   root     1820:     case 0x10: // As if user primary
                   1821:     case 0x18: // As if user primary LE
                   1822:     case 0x80: // Primary
                   1823:     case 0x88: // Primary LE
1.1.1.6 ! root     1824:     case 0xe2: // UA2007 Primary block init
        !          1825:     case 0xe3: // UA2007 Secondary block init
1.1.1.5   root     1826:         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
1.1.1.6 ! root     1827:             if ((env->def->features & CPU_FEATURE_HYPV)
        !          1828:                 && env->hpstate & HS_PRIV) {
1.1.1.5   root     1829:                 switch(size) {
                   1830:                 case 1:
1.1.1.6 ! root     1831:                     stb_hypv(addr, val);
1.1.1.5   root     1832:                     break;
                   1833:                 case 2:
1.1.1.6 ! root     1834:                     stw_hypv(addr, val);
1.1.1.5   root     1835:                     break;
                   1836:                 case 4:
1.1.1.6 ! root     1837:                     stl_hypv(addr, val);
1.1.1.5   root     1838:                     break;
                   1839:                 case 8:
                   1840:                 default:
1.1.1.6 ! root     1841:                     stq_hypv(addr, val);
1.1.1.5   root     1842:                     break;
                   1843:                 }
                   1844:             } else {
                   1845:                 switch(size) {
                   1846:                 case 1:
1.1.1.6 ! root     1847:                     stb_kernel(addr, val);
1.1.1.5   root     1848:                     break;
                   1849:                 case 2:
1.1.1.6 ! root     1850:                     stw_kernel(addr, val);
1.1.1.5   root     1851:                     break;
                   1852:                 case 4:
1.1.1.6 ! root     1853:                     stl_kernel(addr, val);
1.1.1.5   root     1854:                     break;
                   1855:                 case 8:
                   1856:                 default:
1.1.1.6 ! root     1857:                     stq_kernel(addr, val);
1.1.1.5   root     1858:                     break;
                   1859:                 }
                   1860:             }
                   1861:         } else {
                   1862:             switch(size) {
                   1863:             case 1:
1.1.1.6 ! root     1864:                 stb_user(addr, val);
1.1.1.5   root     1865:                 break;
                   1866:             case 2:
1.1.1.6 ! root     1867:                 stw_user(addr, val);
1.1.1.5   root     1868:                 break;
                   1869:             case 4:
1.1.1.6 ! root     1870:                 stl_user(addr, val);
1.1.1.5   root     1871:                 break;
                   1872:             case 8:
                   1873:             default:
1.1.1.6 ! root     1874:                 stq_user(addr, val);
1.1.1.5   root     1875:                 break;
                   1876:             }
                   1877:         }
                   1878:         break;
1.1       root     1879:     case 0x14: // Bypass
                   1880:     case 0x15: // Bypass, non-cacheable
1.1.1.5   root     1881:     case 0x1c: // Bypass LE
                   1882:     case 0x1d: // Bypass, non-cacheable LE
                   1883:         {
1.1.1.2   root     1884:             switch(size) {
                   1885:             case 1:
1.1.1.6 ! root     1886:                 stb_phys(addr, val);
1.1.1.2   root     1887:                 break;
                   1888:             case 2:
1.1.1.6 ! root     1889:                 stw_phys(addr, val);
1.1.1.2   root     1890:                 break;
                   1891:             case 4:
1.1.1.6 ! root     1892:                 stl_phys(addr, val);
1.1.1.2   root     1893:                 break;
                   1894:             case 8:
                   1895:             default:
1.1.1.6 ! root     1896:                 stq_phys(addr, val);
1.1.1.2   root     1897:                 break;
                   1898:             }
1.1.1.5   root     1899:         }
                   1900:         return;
1.1.1.6 ! root     1901:     case 0x24: // Nucleus quad LDD 128 bit atomic
        !          1902:     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
        !          1903:         //  Only ldda allowed
        !          1904:         raise_exception(TT_ILL_INSN);
        !          1905:         return;
1.1       root     1906:     case 0x04: // Nucleus
                   1907:     case 0x0c: // Nucleus Little Endian (LE)
                   1908:     case 0x11: // As if user secondary
                   1909:     case 0x19: // As if user secondary LE
                   1910:     case 0x4a: // UPA config
1.1.1.5   root     1911:     case 0x81: // Secondary
1.1       root     1912:     case 0x89: // Secondary LE
1.1.1.5   root     1913:         // XXX
                   1914:         return;
1.1       root     1915:     case 0x45: // LSU
1.1.1.5   root     1916:         {
                   1917:             uint64_t oldreg;
1.1       root     1918: 
1.1.1.5   root     1919:             oldreg = env->lsu;
1.1.1.6 ! root     1920:             env->lsu = val & (DMMU_E | IMMU_E);
1.1.1.5   root     1921:             // Mappings generated during D/I MMU disabled mode are
                   1922:             // invalid in normal mode
                   1923:             if (oldreg != env->lsu) {
1.1.1.6 ! root     1924:                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
        !          1925:                             oldreg, env->lsu);
1.1       root     1926: #ifdef DEBUG_MMU
1.1.1.5   root     1927:                 dump_mmu(env);
1.1       root     1928: #endif
1.1.1.5   root     1929:                 tlb_flush(env, 1);
                   1930:             }
                   1931:             return;
                   1932:         }
1.1       root     1933:     case 0x50: // I-MMU regs
1.1.1.5   root     1934:         {
1.1.1.6 ! root     1935:             int reg = (addr >> 3) & 0xf;
1.1.1.5   root     1936:             uint64_t oldreg;
                   1937: 
                   1938:             oldreg = env->immuregs[reg];
1.1       root     1939:             switch(reg) {
                   1940:             case 0: // RO
                   1941:             case 4:
                   1942:                 return;
                   1943:             case 1: // Not in I-MMU
                   1944:             case 2:
                   1945:             case 7:
                   1946:             case 8:
                   1947:                 return;
                   1948:             case 3: // SFSR
1.1.1.6 ! root     1949:                 if ((val & 1) == 0)
        !          1950:                     val = 0; // Clear SFSR
1.1       root     1951:                 break;
                   1952:             case 5: // TSB access
                   1953:             case 6: // Tag access
                   1954:             default:
                   1955:                 break;
                   1956:             }
1.1.1.6 ! root     1957:             env->immuregs[reg] = val;
1.1       root     1958:             if (oldreg != env->immuregs[reg]) {
1.1.1.6 ! root     1959:                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
        !          1960:                             PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1.1       root     1961:             }
1.1.1.5   root     1962: #ifdef DEBUG_MMU
                   1963:             dump_mmu(env);
1.1       root     1964: #endif
1.1.1.5   root     1965:             return;
                   1966:         }
1.1       root     1967:     case 0x54: // I-MMU data in
1.1.1.5   root     1968:         {
                   1969:             unsigned int i;
1.1       root     1970: 
1.1.1.5   root     1971:             // Try finding an invalid entry
                   1972:             for (i = 0; i < 64; i++) {
                   1973:                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
                   1974:                     env->itlb_tag[i] = env->immuregs[6];
1.1.1.6 ! root     1975:                     env->itlb_tte[i] = val;
1.1.1.5   root     1976:                     return;
                   1977:                 }
                   1978:             }
                   1979:             // Try finding an unlocked entry
                   1980:             for (i = 0; i < 64; i++) {
                   1981:                 if ((env->itlb_tte[i] & 0x40) == 0) {
                   1982:                     env->itlb_tag[i] = env->immuregs[6];
1.1.1.6 ! root     1983:                     env->itlb_tte[i] = val;
1.1.1.5   root     1984:                     return;
                   1985:                 }
                   1986:             }
                   1987:             // error state?
                   1988:             return;
                   1989:         }
1.1       root     1990:     case 0x55: // I-MMU data access
1.1.1.5   root     1991:         {
1.1.1.6 ! root     1992:             // TODO: auto demap
        !          1993: 
        !          1994:             unsigned int i = (addr >> 3) & 0x3f;
1.1       root     1995: 
1.1.1.5   root     1996:             env->itlb_tag[i] = env->immuregs[6];
1.1.1.6 ! root     1997:             env->itlb_tte[i] = val;
1.1.1.5   root     1998:             return;
                   1999:         }
1.1       root     2000:     case 0x57: // I-MMU demap
1.1.1.6 ! root     2001:         {
        !          2002:             unsigned int i;
        !          2003: 
        !          2004:             for (i = 0; i < 64; i++) {
        !          2005:                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
        !          2006:                     target_ulong mask = 0xffffffffffffe000ULL;
        !          2007: 
        !          2008:                     mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
        !          2009:                     if ((val & mask) == (env->itlb_tag[i] & mask)) {
        !          2010:                         env->itlb_tag[i] = 0;
        !          2011:                         env->itlb_tte[i] = 0;
        !          2012:                     }
        !          2013:                     return;
        !          2014:                 }
        !          2015:             }
        !          2016:         }
1.1.1.5   root     2017:         return;
1.1       root     2018:     case 0x58: // D-MMU regs
1.1.1.5   root     2019:         {
1.1.1.6 ! root     2020:             int reg = (addr >> 3) & 0xf;
1.1.1.5   root     2021:             uint64_t oldreg;
                   2022: 
                   2023:             oldreg = env->dmmuregs[reg];
1.1       root     2024:             switch(reg) {
                   2025:             case 0: // RO
                   2026:             case 4:
                   2027:                 return;
                   2028:             case 3: // SFSR
1.1.1.6 ! root     2029:                 if ((val & 1) == 0) {
        !          2030:                     val = 0; // Clear SFSR, Fault address
1.1.1.5   root     2031:                     env->dmmuregs[4] = 0;
                   2032:                 }
1.1.1.6 ! root     2033:                 env->dmmuregs[reg] = val;
1.1       root     2034:                 break;
                   2035:             case 1: // Primary context
                   2036:             case 2: // Secondary context
                   2037:             case 5: // TSB access
                   2038:             case 6: // Tag access
                   2039:             case 7: // Virtual Watchpoint
                   2040:             case 8: // Physical Watchpoint
                   2041:             default:
                   2042:                 break;
                   2043:             }
1.1.1.6 ! root     2044:             env->dmmuregs[reg] = val;
1.1       root     2045:             if (oldreg != env->dmmuregs[reg]) {
1.1.1.6 ! root     2046:                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"
        !          2047:                             PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1.1       root     2048:             }
1.1.1.5   root     2049: #ifdef DEBUG_MMU
                   2050:             dump_mmu(env);
1.1       root     2051: #endif
1.1.1.5   root     2052:             return;
                   2053:         }
1.1       root     2054:     case 0x5c: // D-MMU data in
1.1.1.5   root     2055:         {
                   2056:             unsigned int i;
1.1       root     2057: 
1.1.1.5   root     2058:             // Try finding an invalid entry
                   2059:             for (i = 0; i < 64; i++) {
                   2060:                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
                   2061:                     env->dtlb_tag[i] = env->dmmuregs[6];
1.1.1.6 ! root     2062:                     env->dtlb_tte[i] = val;
1.1.1.5   root     2063:                     return;
                   2064:                 }
                   2065:             }
                   2066:             // Try finding an unlocked entry
                   2067:             for (i = 0; i < 64; i++) {
                   2068:                 if ((env->dtlb_tte[i] & 0x40) == 0) {
                   2069:                     env->dtlb_tag[i] = env->dmmuregs[6];
1.1.1.6 ! root     2070:                     env->dtlb_tte[i] = val;
1.1.1.5   root     2071:                     return;
                   2072:                 }
                   2073:             }
                   2074:             // error state?
                   2075:             return;
                   2076:         }
1.1       root     2077:     case 0x5d: // D-MMU data access
1.1.1.5   root     2078:         {
1.1.1.6 ! root     2079:             unsigned int i = (addr >> 3) & 0x3f;
1.1       root     2080: 
1.1.1.5   root     2081:             env->dtlb_tag[i] = env->dmmuregs[6];
1.1.1.6 ! root     2082:             env->dtlb_tte[i] = val;
1.1.1.5   root     2083:             return;
                   2084:         }
1.1       root     2085:     case 0x5f: // D-MMU demap
1.1.1.6 ! root     2086:         {
        !          2087:             unsigned int i;
        !          2088: 
        !          2089:             for (i = 0; i < 64; i++) {
        !          2090:                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
        !          2091:                     target_ulong mask = 0xffffffffffffe000ULL;
        !          2092: 
        !          2093:                     mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
        !          2094:                     if ((val & mask) == (env->dtlb_tag[i] & mask)) {
        !          2095:                         env->dtlb_tag[i] = 0;
        !          2096:                         env->dtlb_tte[i] = 0;
        !          2097:                     }
        !          2098:                     return;
        !          2099:                 }
        !          2100:             }
        !          2101:         }
        !          2102:         return;
1.1       root     2103:     case 0x49: // Interrupt data receive
1.1.1.5   root     2104:         // XXX
                   2105:         return;
1.1.1.6 ! root     2106:     case 0x46: // D-cache data
        !          2107:     case 0x47: // D-cache tag access
        !          2108:     case 0x4b: // E-cache error enable
        !          2109:     case 0x4c: // E-cache asynchronous fault status
        !          2110:     case 0x4d: // E-cache asynchronous fault address
        !          2111:     case 0x4e: // E-cache tag data
        !          2112:     case 0x66: // I-cache instruction access
        !          2113:     case 0x67: // I-cache tag access
        !          2114:     case 0x6e: // I-cache predecode
        !          2115:     case 0x6f: // I-cache LRU etc.
        !          2116:     case 0x76: // E-cache tag
        !          2117:     case 0x7e: // E-cache tag
        !          2118:         return;
1.1       root     2119:     case 0x51: // I-MMU 8k TSB pointer, RO
                   2120:     case 0x52: // I-MMU 64k TSB pointer, RO
                   2121:     case 0x56: // I-MMU tag read, RO
                   2122:     case 0x59: // D-MMU 8k TSB pointer, RO
                   2123:     case 0x5a: // D-MMU 64k TSB pointer, RO
                   2124:     case 0x5b: // D-MMU data pointer, RO
                   2125:     case 0x5e: // D-MMU tag read, RO
                   2126:     case 0x48: // Interrupt dispatch, RO
                   2127:     case 0x7f: // Incoming interrupt vector, RO
                   2128:     case 0x82: // Primary no-fault, RO
                   2129:     case 0x83: // Secondary no-fault, RO
                   2130:     case 0x8a: // Primary no-fault LE, RO
                   2131:     case 0x8b: // Secondary no-fault LE, RO
                   2132:     default:
1.1.1.6 ! root     2133:         do_unassigned_access(addr, 1, 0, 1, size);
1.1.1.5   root     2134:         return;
                   2135:     }
                   2136: }
                   2137: #endif /* CONFIG_USER_ONLY */
                   2138: 
1.1.1.6 ! root     2139: void helper_ldda_asi(target_ulong addr, int asi, int rd)
        !          2140: {
        !          2141:     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
        !          2142:         || ((env->def->features & CPU_FEATURE_HYPV)
        !          2143:             && asi >= 0x30 && asi < 0x80
        !          2144:             && !(env->hpstate & HS_PRIV)))
        !          2145:         raise_exception(TT_PRIV_ACT);
        !          2146: 
        !          2147:     switch (asi) {
        !          2148:     case 0x24: // Nucleus quad LDD 128 bit atomic
        !          2149:     case 0x2c: // Nucleus quad LDD 128 bit atomic LE
        !          2150:         helper_check_align(addr, 0xf);
        !          2151:         if (rd == 0) {
        !          2152:             env->gregs[1] = ldq_kernel(addr + 8);
        !          2153:             if (asi == 0x2c)
        !          2154:                 bswap64s(&env->gregs[1]);
        !          2155:         } else if (rd < 8) {
        !          2156:             env->gregs[rd] = ldq_kernel(addr);
        !          2157:             env->gregs[rd + 1] = ldq_kernel(addr + 8);
        !          2158:             if (asi == 0x2c) {
        !          2159:                 bswap64s(&env->gregs[rd]);
        !          2160:                 bswap64s(&env->gregs[rd + 1]);
        !          2161:             }
        !          2162:         } else {
        !          2163:             env->regwptr[rd] = ldq_kernel(addr);
        !          2164:             env->regwptr[rd + 1] = ldq_kernel(addr + 8);
        !          2165:             if (asi == 0x2c) {
        !          2166:                 bswap64s(&env->regwptr[rd]);
        !          2167:                 bswap64s(&env->regwptr[rd + 1]);
        !          2168:             }
        !          2169:         }
        !          2170:         break;
        !          2171:     default:
        !          2172:         helper_check_align(addr, 0x3);
        !          2173:         if (rd == 0)
        !          2174:             env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
        !          2175:         else if (rd < 8) {
        !          2176:             env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
        !          2177:             env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
        !          2178:         } else {
        !          2179:             env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
        !          2180:             env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
        !          2181:         }
        !          2182:         break;
        !          2183:     }
        !          2184: }
        !          2185: 
        !          2186: void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
1.1.1.5   root     2187: {
                   2188:     unsigned int i;
1.1.1.6 ! root     2189:     target_ulong val;
1.1.1.5   root     2190: 
1.1.1.6 ! root     2191:     helper_check_align(addr, 3);
1.1.1.5   root     2192:     switch (asi) {
                   2193:     case 0xf0: // Block load primary
                   2194:     case 0xf1: // Block load secondary
                   2195:     case 0xf8: // Block load primary LE
                   2196:     case 0xf9: // Block load secondary LE
                   2197:         if (rd & 7) {
                   2198:             raise_exception(TT_ILL_INSN);
                   2199:             return;
                   2200:         }
1.1.1.6 ! root     2201:         helper_check_align(addr, 0x3f);
1.1.1.5   root     2202:         for (i = 0; i < 16; i++) {
1.1.1.6 ! root     2203:             *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,
        !          2204:                                                          0);
        !          2205:             addr += 4;
1.1.1.5   root     2206:         }
                   2207: 
                   2208:         return;
                   2209:     default:
                   2210:         break;
                   2211:     }
                   2212: 
1.1.1.6 ! root     2213:     val = helper_ld_asi(addr, asi, size, 0);
1.1.1.5   root     2214:     switch(size) {
                   2215:     default:
                   2216:     case 4:
1.1.1.6 ! root     2217:         *((uint32_t *)&env->fpr[rd]) = val;
1.1.1.5   root     2218:         break;
                   2219:     case 8:
1.1.1.6 ! root     2220:         *((int64_t *)&DT0) = val;
1.1.1.5   root     2221:         break;
                   2222:     case 16:
                   2223:         // XXX
                   2224:         break;
1.1       root     2225:     }
                   2226: }
1.1.1.5   root     2227: 
1.1.1.6 ! root     2228: void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
1.1.1.5   root     2229: {
                   2230:     unsigned int i;
1.1.1.6 ! root     2231:     target_ulong val = 0;
1.1.1.5   root     2232: 
1.1.1.6 ! root     2233:     helper_check_align(addr, 3);
1.1.1.5   root     2234:     switch (asi) {
1.1.1.6 ! root     2235:     case 0xe0: // UA2007 Block commit store primary (cache flush)
        !          2236:     case 0xe1: // UA2007 Block commit store secondary (cache flush)
1.1.1.5   root     2237:     case 0xf0: // Block store primary
                   2238:     case 0xf1: // Block store secondary
                   2239:     case 0xf8: // Block store primary LE
                   2240:     case 0xf9: // Block store secondary LE
                   2241:         if (rd & 7) {
                   2242:             raise_exception(TT_ILL_INSN);
                   2243:             return;
                   2244:         }
1.1.1.6 ! root     2245:         helper_check_align(addr, 0x3f);
1.1.1.5   root     2246:         for (i = 0; i < 16; i++) {
1.1.1.6 ! root     2247:             val = *(uint32_t *)&env->fpr[rd++];
        !          2248:             helper_st_asi(addr, val, asi & 0x8f, 4);
        !          2249:             addr += 4;
1.1.1.5   root     2250:         }
                   2251: 
                   2252:         return;
                   2253:     default:
                   2254:         break;
                   2255:     }
                   2256: 
                   2257:     switch(size) {
                   2258:     default:
                   2259:     case 4:
1.1.1.6 ! root     2260:         val = *((uint32_t *)&env->fpr[rd]);
1.1.1.5   root     2261:         break;
                   2262:     case 8:
1.1.1.6 ! root     2263:         val = *((int64_t *)&DT0);
1.1.1.5   root     2264:         break;
                   2265:     case 16:
                   2266:         // XXX
                   2267:         break;
                   2268:     }
1.1.1.6 ! root     2269:     helper_st_asi(addr, val, asi, size);
        !          2270: }
        !          2271: 
        !          2272: target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
        !          2273:                             target_ulong val2, uint32_t asi)
        !          2274: {
        !          2275:     target_ulong ret;
        !          2276: 
        !          2277:     val2 &= 0xffffffffUL;
        !          2278:     ret = helper_ld_asi(addr, asi, 4, 0);
        !          2279:     ret &= 0xffffffffUL;
        !          2280:     if (val2 == ret)
        !          2281:         helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
        !          2282:     return ret;
1.1.1.5   root     2283: }
                   2284: 
1.1.1.6 ! root     2285: target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
        !          2286:                              target_ulong val2, uint32_t asi)
        !          2287: {
        !          2288:     target_ulong ret;
        !          2289: 
        !          2290:     ret = helper_ld_asi(addr, asi, 8, 0);
        !          2291:     if (val2 == ret)
        !          2292:         helper_st_asi(addr, val1, asi, 8);
        !          2293:     return ret;
        !          2294: }
1.1.1.5   root     2295: #endif /* TARGET_SPARC64 */
1.1       root     2296: 
                   2297: #ifndef TARGET_SPARC64
1.1.1.6 ! root     2298: void helper_rett(void)
1.1       root     2299: {
                   2300:     unsigned int cwp;
                   2301: 
1.1.1.5   root     2302:     if (env->psret == 1)
                   2303:         raise_exception(TT_ILL_INSN);
                   2304: 
1.1       root     2305:     env->psret = 1;
1.1.1.6 ! root     2306:     cwp = cpu_cwp_inc(env, env->cwp + 1) ;
1.1       root     2307:     if (env->wim & (1 << cwp)) {
                   2308:         raise_exception(TT_WIN_UNF);
                   2309:     }
                   2310:     set_cwp(cwp);
                   2311:     env->psrs = env->psrps;
                   2312: }
                   2313: #endif
                   2314: 
1.1.1.6 ! root     2315: target_ulong helper_udiv(target_ulong a, target_ulong b)
        !          2316: {
        !          2317:     uint64_t x0;
        !          2318:     uint32_t x1;
        !          2319: 
        !          2320:     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
        !          2321:     x1 = b;
        !          2322: 
        !          2323:     if (x1 == 0) {
        !          2324:         raise_exception(TT_DIV_ZERO);
        !          2325:     }
        !          2326: 
        !          2327:     x0 = x0 / x1;
        !          2328:     if (x0 > 0xffffffff) {
        !          2329:         env->cc_src2 = 1;
        !          2330:         return 0xffffffff;
        !          2331:     } else {
        !          2332:         env->cc_src2 = 0;
        !          2333:         return x0;
        !          2334:     }
        !          2335: }
        !          2336: 
        !          2337: target_ulong helper_sdiv(target_ulong a, target_ulong b)
        !          2338: {
        !          2339:     int64_t x0;
        !          2340:     int32_t x1;
        !          2341: 
        !          2342:     x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
        !          2343:     x1 = b;
        !          2344: 
        !          2345:     if (x1 == 0) {
        !          2346:         raise_exception(TT_DIV_ZERO);
        !          2347:     }
        !          2348: 
        !          2349:     x0 = x0 / x1;
        !          2350:     if ((int32_t) x0 != x0) {
        !          2351:         env->cc_src2 = 1;
        !          2352:         return x0 < 0? 0x80000000: 0x7fffffff;
        !          2353:     } else {
        !          2354:         env->cc_src2 = 0;
        !          2355:         return x0;
        !          2356:     }
        !          2357: }
        !          2358: 
        !          2359: void helper_stdf(target_ulong addr, int mem_idx)
        !          2360: {
        !          2361:     helper_check_align(addr, 7);
        !          2362: #if !defined(CONFIG_USER_ONLY)
        !          2363:     switch (mem_idx) {
        !          2364:     case 0:
        !          2365:         stfq_user(addr, DT0);
        !          2366:         break;
        !          2367:     case 1:
        !          2368:         stfq_kernel(addr, DT0);
        !          2369:         break;
        !          2370: #ifdef TARGET_SPARC64
        !          2371:     case 2:
        !          2372:         stfq_hypv(addr, DT0);
        !          2373:         break;
        !          2374: #endif
        !          2375:     default:
        !          2376:         break;
        !          2377:     }
        !          2378: #else
        !          2379:     address_mask(env, &addr);
        !          2380:     stfq_raw(addr, DT0);
        !          2381: #endif
        !          2382: }
        !          2383: 
        !          2384: void helper_lddf(target_ulong addr, int mem_idx)
        !          2385: {
        !          2386:     helper_check_align(addr, 7);
        !          2387: #if !defined(CONFIG_USER_ONLY)
        !          2388:     switch (mem_idx) {
        !          2389:     case 0:
        !          2390:         DT0 = ldfq_user(addr);
        !          2391:         break;
        !          2392:     case 1:
        !          2393:         DT0 = ldfq_kernel(addr);
        !          2394:         break;
        !          2395: #ifdef TARGET_SPARC64
        !          2396:     case 2:
        !          2397:         DT0 = ldfq_hypv(addr);
        !          2398:         break;
        !          2399: #endif
        !          2400:     default:
        !          2401:         break;
        !          2402:     }
        !          2403: #else
        !          2404:     address_mask(env, &addr);
        !          2405:     DT0 = ldfq_raw(addr);
        !          2406: #endif
        !          2407: }
        !          2408: 
        !          2409: void helper_ldqf(target_ulong addr, int mem_idx)
        !          2410: {
        !          2411:     // XXX add 128 bit load
        !          2412:     CPU_QuadU u;
        !          2413: 
        !          2414:     helper_check_align(addr, 7);
        !          2415: #if !defined(CONFIG_USER_ONLY)
        !          2416:     switch (mem_idx) {
        !          2417:     case 0:
        !          2418:         u.ll.upper = ldq_user(addr);
        !          2419:         u.ll.lower = ldq_user(addr + 8);
        !          2420:         QT0 = u.q;
        !          2421:         break;
        !          2422:     case 1:
        !          2423:         u.ll.upper = ldq_kernel(addr);
        !          2424:         u.ll.lower = ldq_kernel(addr + 8);
        !          2425:         QT0 = u.q;
        !          2426:         break;
        !          2427: #ifdef TARGET_SPARC64
        !          2428:     case 2:
        !          2429:         u.ll.upper = ldq_hypv(addr);
        !          2430:         u.ll.lower = ldq_hypv(addr + 8);
        !          2431:         QT0 = u.q;
        !          2432:         break;
        !          2433: #endif
        !          2434:     default:
        !          2435:         break;
        !          2436:     }
        !          2437: #else
        !          2438:     address_mask(env, &addr);
        !          2439:     u.ll.upper = ldq_raw(addr);
        !          2440:     u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);
        !          2441:     QT0 = u.q;
        !          2442: #endif
        !          2443: }
        !          2444: 
        !          2445: void helper_stqf(target_ulong addr, int mem_idx)
        !          2446: {
        !          2447:     // XXX add 128 bit store
        !          2448:     CPU_QuadU u;
        !          2449: 
        !          2450:     helper_check_align(addr, 7);
        !          2451: #if !defined(CONFIG_USER_ONLY)
        !          2452:     switch (mem_idx) {
        !          2453:     case 0:
        !          2454:         u.q = QT0;
        !          2455:         stq_user(addr, u.ll.upper);
        !          2456:         stq_user(addr + 8, u.ll.lower);
        !          2457:         break;
        !          2458:     case 1:
        !          2459:         u.q = QT0;
        !          2460:         stq_kernel(addr, u.ll.upper);
        !          2461:         stq_kernel(addr + 8, u.ll.lower);
        !          2462:         break;
        !          2463: #ifdef TARGET_SPARC64
        !          2464:     case 2:
        !          2465:         u.q = QT0;
        !          2466:         stq_hypv(addr, u.ll.upper);
        !          2467:         stq_hypv(addr + 8, u.ll.lower);
        !          2468:         break;
        !          2469: #endif
        !          2470:     default:
        !          2471:         break;
        !          2472:     }
        !          2473: #else
        !          2474:     u.q = QT0;
        !          2475:     address_mask(env, &addr);
        !          2476:     stq_raw(addr, u.ll.upper);
        !          2477:     stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);
        !          2478: #endif
        !          2479: }
        !          2480: 
        !          2481: static inline void set_fsr(void)
1.1       root     2482: {
                   2483:     int rnd_mode;
1.1.1.6 ! root     2484: 
1.1       root     2485:     switch (env->fsr & FSR_RD_MASK) {
                   2486:     case FSR_RD_NEAREST:
                   2487:         rnd_mode = float_round_nearest_even;
1.1.1.5   root     2488:         break;
1.1       root     2489:     default:
                   2490:     case FSR_RD_ZERO:
                   2491:         rnd_mode = float_round_to_zero;
1.1.1.5   root     2492:         break;
1.1       root     2493:     case FSR_RD_POS:
                   2494:         rnd_mode = float_round_up;
1.1.1.5   root     2495:         break;
1.1       root     2496:     case FSR_RD_NEG:
                   2497:         rnd_mode = float_round_down;
1.1.1.5   root     2498:         break;
1.1       root     2499:     }
                   2500:     set_float_rounding_mode(rnd_mode, &env->fp_status);
                   2501: }
                   2502: 
1.1.1.6 ! root     2503: void helper_ldfsr(uint32_t new_fsr)
        !          2504: {
        !          2505:     env->fsr = (new_fsr & FSR_LDFSR_MASK) | (env->fsr & FSR_LDFSR_OLDMASK);
        !          2506:     set_fsr();
        !          2507: }
        !          2508: 
        !          2509: #ifdef TARGET_SPARC64
        !          2510: void helper_ldxfsr(uint64_t new_fsr)
        !          2511: {
        !          2512:     env->fsr = (new_fsr & FSR_LDXFSR_MASK) | (env->fsr & FSR_LDXFSR_OLDMASK);
        !          2513:     set_fsr();
        !          2514: }
        !          2515: #endif
        !          2516: 
        !          2517: void helper_debug(void)
1.1       root     2518: {
                   2519:     env->exception_index = EXCP_DEBUG;
                   2520:     cpu_loop_exit();
                   2521: }
                   2522: 
                   2523: #ifndef TARGET_SPARC64
1.1.1.6 ! root     2524: /* XXX: use another pointer for %iN registers to avoid slow wrapping
        !          2525:    handling ? */
        !          2526: void helper_save(void)
        !          2527: {
        !          2528:     uint32_t cwp;
        !          2529: 
        !          2530:     cwp = cpu_cwp_dec(env, env->cwp - 1);
        !          2531:     if (env->wim & (1 << cwp)) {
        !          2532:         raise_exception(TT_WIN_OVF);
        !          2533:     }
        !          2534:     set_cwp(cwp);
        !          2535: }
        !          2536: 
        !          2537: void helper_restore(void)
        !          2538: {
        !          2539:     uint32_t cwp;
        !          2540: 
        !          2541:     cwp = cpu_cwp_inc(env, env->cwp + 1);
        !          2542:     if (env->wim & (1 << cwp)) {
        !          2543:         raise_exception(TT_WIN_UNF);
        !          2544:     }
        !          2545:     set_cwp(cwp);
        !          2546: }
        !          2547: 
        !          2548: void helper_wrpsr(target_ulong new_psr)
1.1       root     2549: {
1.1.1.6 ! root     2550:     if ((new_psr & PSR_CWP) >= env->nwindows)
1.1.1.5   root     2551:         raise_exception(TT_ILL_INSN);
                   2552:     else
1.1.1.6 ! root     2553:         PUT_PSR(env, new_psr);
1.1       root     2554: }
                   2555: 
1.1.1.6 ! root     2556: target_ulong helper_rdpsr(void)
1.1       root     2557: {
1.1.1.6 ! root     2558:     return GET_PSR(env);
1.1       root     2559: }
                   2560: 
                   2561: #else
1.1.1.6 ! root     2562: /* XXX: use another pointer for %iN registers to avoid slow wrapping
        !          2563:    handling ? */
        !          2564: void helper_save(void)
        !          2565: {
        !          2566:     uint32_t cwp;
        !          2567: 
        !          2568:     cwp = cpu_cwp_dec(env, env->cwp - 1);
        !          2569:     if (env->cansave == 0) {
        !          2570:         raise_exception(TT_SPILL | (env->otherwin != 0 ?
        !          2571:                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
        !          2572:                                     ((env->wstate & 0x7) << 2)));
        !          2573:     } else {
        !          2574:         if (env->cleanwin - env->canrestore == 0) {
        !          2575:             // XXX Clean windows without trap
        !          2576:             raise_exception(TT_CLRWIN);
        !          2577:         } else {
        !          2578:             env->cansave--;
        !          2579:             env->canrestore++;
        !          2580:             set_cwp(cwp);
        !          2581:         }
        !          2582:     }
        !          2583: }
        !          2584: 
        !          2585: void helper_restore(void)
        !          2586: {
        !          2587:     uint32_t cwp;
        !          2588: 
        !          2589:     cwp = cpu_cwp_inc(env, env->cwp + 1);
        !          2590:     if (env->canrestore == 0) {
        !          2591:         raise_exception(TT_FILL | (env->otherwin != 0 ?
        !          2592:                                    (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
        !          2593:                                    ((env->wstate & 0x7) << 2)));
        !          2594:     } else {
        !          2595:         env->cansave++;
        !          2596:         env->canrestore--;
        !          2597:         set_cwp(cwp);
        !          2598:     }
        !          2599: }
        !          2600: 
        !          2601: void helper_flushw(void)
        !          2602: {
        !          2603:     if (env->cansave != env->nwindows - 2) {
        !          2604:         raise_exception(TT_SPILL | (env->otherwin != 0 ?
        !          2605:                                     (TT_WOTHER | ((env->wstate & 0x38) >> 1)):
        !          2606:                                     ((env->wstate & 0x7) << 2)));
        !          2607:     }
        !          2608: }
        !          2609: 
        !          2610: void helper_saved(void)
        !          2611: {
        !          2612:     env->cansave++;
        !          2613:     if (env->otherwin == 0)
        !          2614:         env->canrestore--;
        !          2615:     else
        !          2616:         env->otherwin--;
        !          2617: }
1.1       root     2618: 
1.1.1.6 ! root     2619: void helper_restored(void)
1.1       root     2620: {
1.1.1.6 ! root     2621:     env->canrestore++;
        !          2622:     if (env->cleanwin < env->nwindows - 1)
        !          2623:         env->cleanwin++;
        !          2624:     if (env->otherwin == 0)
        !          2625:         env->cansave--;
        !          2626:     else
        !          2627:         env->otherwin--;
        !          2628: }
        !          2629: 
        !          2630: target_ulong helper_rdccr(void)
        !          2631: {
        !          2632:     return GET_CCR(env);
        !          2633: }
        !          2634: 
        !          2635: void helper_wrccr(target_ulong new_ccr)
        !          2636: {
        !          2637:     PUT_CCR(env, new_ccr);
        !          2638: }
        !          2639: 
        !          2640: // CWP handling is reversed in V9, but we still use the V8 register
        !          2641: // order.
        !          2642: target_ulong helper_rdcwp(void)
        !          2643: {
        !          2644:     return GET_CWP64(env);
        !          2645: }
        !          2646: 
        !          2647: void helper_wrcwp(target_ulong new_cwp)
        !          2648: {
        !          2649:     PUT_CWP64(env, new_cwp);
        !          2650: }
        !          2651: 
        !          2652: // This function uses non-native bit order
        !          2653: #define GET_FIELD(X, FROM, TO)                                  \
        !          2654:     ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
        !          2655: 
        !          2656: // This function uses the order in the manuals, i.e. bit 0 is 2^0
        !          2657: #define GET_FIELD_SP(X, FROM, TO)               \
        !          2658:     GET_FIELD(X, 63 - (TO), 63 - (FROM))
        !          2659: 
        !          2660: target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
        !          2661: {
        !          2662:     return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
        !          2663:         (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
        !          2664:         (GET_FIELD_SP(pixel_addr, 17 + cubesize - 1, 17) << 17) |
        !          2665:         (GET_FIELD_SP(pixel_addr, 56, 59) << 13) |
        !          2666:         (GET_FIELD_SP(pixel_addr, 35, 38) << 9) |
        !          2667:         (GET_FIELD_SP(pixel_addr, 13, 16) << 5) |
        !          2668:         (((pixel_addr >> 55) & 1) << 4) |
        !          2669:         (GET_FIELD_SP(pixel_addr, 33, 34) << 2) |
        !          2670:         GET_FIELD_SP(pixel_addr, 11, 12);
        !          2671: }
        !          2672: 
        !          2673: target_ulong helper_alignaddr(target_ulong addr, target_ulong offset)
        !          2674: {
        !          2675:     uint64_t tmp;
        !          2676: 
        !          2677:     tmp = addr + offset;
        !          2678:     env->gsr &= ~7ULL;
        !          2679:     env->gsr |= tmp & 7ULL;
        !          2680:     return tmp & ~7ULL;
        !          2681: }
        !          2682: 
        !          2683: target_ulong helper_popc(target_ulong val)
        !          2684: {
        !          2685:     return ctpop64(val);
1.1       root     2686: }
                   2687: 
                   2688: static inline uint64_t *get_gregset(uint64_t pstate)
                   2689: {
                   2690:     switch (pstate) {
                   2691:     default:
                   2692:     case 0:
1.1.1.5   root     2693:         return env->bgregs;
1.1       root     2694:     case PS_AG:
1.1.1.5   root     2695:         return env->agregs;
1.1       root     2696:     case PS_MG:
1.1.1.5   root     2697:         return env->mgregs;
1.1       root     2698:     case PS_IG:
1.1.1.5   root     2699:         return env->igregs;
1.1       root     2700:     }
                   2701: }
                   2702: 
1.1.1.5   root     2703: static inline void change_pstate(uint64_t new_pstate)
1.1       root     2704: {
1.1.1.5   root     2705:     uint64_t pstate_regs, new_pstate_regs;
1.1       root     2706:     uint64_t *src, *dst;
                   2707: 
                   2708:     pstate_regs = env->pstate & 0xc01;
                   2709:     new_pstate_regs = new_pstate & 0xc01;
                   2710:     if (new_pstate_regs != pstate_regs) {
1.1.1.5   root     2711:         // Switch global register bank
                   2712:         src = get_gregset(new_pstate_regs);
                   2713:         dst = get_gregset(pstate_regs);
                   2714:         memcpy32(dst, env->gregs);
                   2715:         memcpy32(env->gregs, src);
1.1       root     2716:     }
                   2717:     env->pstate = new_pstate;
                   2718: }
                   2719: 
1.1.1.6 ! root     2720: void helper_wrpstate(target_ulong new_state)
1.1.1.5   root     2721: {
1.1.1.6 ! root     2722:     if (!(env->def->features & CPU_FEATURE_GL))
        !          2723:         change_pstate(new_state & 0xf3f);
1.1.1.5   root     2724: }
                   2725: 
1.1.1.6 ! root     2726: void helper_done(void)
1.1       root     2727: {
1.1.1.6 ! root     2728:     env->pc = env->tsptr->tpc;
        !          2729:     env->npc = env->tsptr->tnpc + 4;
        !          2730:     PUT_CCR(env, env->tsptr->tstate >> 32);
        !          2731:     env->asi = (env->tsptr->tstate >> 24) & 0xff;
        !          2732:     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
        !          2733:     PUT_CWP64(env, env->tsptr->tstate & 0xff);
1.1       root     2734:     env->tl--;
1.1.1.6 ! root     2735:     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
1.1       root     2736: }
                   2737: 
1.1.1.6 ! root     2738: void helper_retry(void)
1.1       root     2739: {
1.1.1.6 ! root     2740:     env->pc = env->tsptr->tpc;
        !          2741:     env->npc = env->tsptr->tnpc;
        !          2742:     PUT_CCR(env, env->tsptr->tstate >> 32);
        !          2743:     env->asi = (env->tsptr->tstate >> 24) & 0xff;
        !          2744:     change_pstate((env->tsptr->tstate >> 8) & 0xf3f);
        !          2745:     PUT_CWP64(env, env->tsptr->tstate & 0xff);
1.1       root     2746:     env->tl--;
1.1.1.6 ! root     2747:     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
1.1       root     2748: }
                   2749: 
1.1.1.6 ! root     2750: void helper_set_softint(uint64_t value)
1.1       root     2751: {
1.1.1.6 ! root     2752:     env->softint |= (uint32_t)value;
1.1       root     2753: }
                   2754: 
1.1.1.6 ! root     2755: void helper_clear_softint(uint64_t value)
1.1       root     2756: {
1.1.1.6 ! root     2757:     env->softint &= (uint32_t)~value;
        !          2758: }
1.1       root     2759: 
1.1.1.6 ! root     2760: void helper_write_softint(uint64_t value)
        !          2761: {
        !          2762:     env->softint = (uint32_t)value;
        !          2763: }
1.1       root     2764: #endif
1.1.1.6 ! root     2765: 
        !          2766: void helper_flush(target_ulong addr)
        !          2767: {
        !          2768:     addr &= ~7;
        !          2769:     tb_invalidate_page_range(addr, addr + 8);
1.1       root     2770: }
                   2771: 
                   2772: #ifdef TARGET_SPARC64
1.1.1.5   root     2773: #ifdef DEBUG_PCALL
1.1.1.6 ! root     2774: static const char * const excp_names[0x80] = {
1.1.1.5   root     2775:     [TT_TFAULT] = "Instruction Access Fault",
                   2776:     [TT_TMISS] = "Instruction Access MMU Miss",
                   2777:     [TT_CODE_ACCESS] = "Instruction Access Error",
                   2778:     [TT_ILL_INSN] = "Illegal Instruction",
                   2779:     [TT_PRIV_INSN] = "Privileged Instruction",
                   2780:     [TT_NFPU_INSN] = "FPU Disabled",
                   2781:     [TT_FP_EXCP] = "FPU Exception",
                   2782:     [TT_TOVF] = "Tag Overflow",
                   2783:     [TT_CLRWIN] = "Clean Windows",
                   2784:     [TT_DIV_ZERO] = "Division By Zero",
                   2785:     [TT_DFAULT] = "Data Access Fault",
                   2786:     [TT_DMISS] = "Data Access MMU Miss",
                   2787:     [TT_DATA_ACCESS] = "Data Access Error",
                   2788:     [TT_DPROT] = "Data Protection Error",
                   2789:     [TT_UNALIGNED] = "Unaligned Memory Access",
                   2790:     [TT_PRIV_ACT] = "Privileged Action",
                   2791:     [TT_EXTINT | 0x1] = "External Interrupt 1",
                   2792:     [TT_EXTINT | 0x2] = "External Interrupt 2",
                   2793:     [TT_EXTINT | 0x3] = "External Interrupt 3",
                   2794:     [TT_EXTINT | 0x4] = "External Interrupt 4",
                   2795:     [TT_EXTINT | 0x5] = "External Interrupt 5",
                   2796:     [TT_EXTINT | 0x6] = "External Interrupt 6",
                   2797:     [TT_EXTINT | 0x7] = "External Interrupt 7",
                   2798:     [TT_EXTINT | 0x8] = "External Interrupt 8",
                   2799:     [TT_EXTINT | 0x9] = "External Interrupt 9",
                   2800:     [TT_EXTINT | 0xa] = "External Interrupt 10",
                   2801:     [TT_EXTINT | 0xb] = "External Interrupt 11",
                   2802:     [TT_EXTINT | 0xc] = "External Interrupt 12",
                   2803:     [TT_EXTINT | 0xd] = "External Interrupt 13",
                   2804:     [TT_EXTINT | 0xe] = "External Interrupt 14",
                   2805:     [TT_EXTINT | 0xf] = "External Interrupt 15",
                   2806: };
                   2807: #endif
                   2808: 
1.1.1.6 ! root     2809: void do_interrupt(CPUState *env)
1.1       root     2810: {
1.1.1.6 ! root     2811:     int intno = env->exception_index;
        !          2812: 
1.1       root     2813: #ifdef DEBUG_PCALL
1.1.1.6 ! root     2814:     if (qemu_loglevel_mask(CPU_LOG_INT)) {
1.1.1.5   root     2815:         static int count;
                   2816:         const char *name;
                   2817: 
1.1.1.6 ! root     2818:         if (intno < 0 || intno >= 0x180)
1.1.1.5   root     2819:             name = "Unknown";
                   2820:         else if (intno >= 0x100)
                   2821:             name = "Trap Instruction";
                   2822:         else if (intno >= 0xc0)
                   2823:             name = "Window Fill";
                   2824:         else if (intno >= 0x80)
                   2825:             name = "Window Spill";
                   2826:         else {
                   2827:             name = excp_names[intno];
                   2828:             if (!name)
                   2829:                 name = "Unknown";
                   2830:         }
                   2831: 
1.1.1.6 ! root     2832:         qemu_log("%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
1.1.1.5   root     2833:                 " SP=%016" PRIx64 "\n",
                   2834:                 count, name, intno,
1.1       root     2835:                 env->pc,
                   2836:                 env->npc, env->regwptr[6]);
1.1.1.6 ! root     2837:         log_cpu_state(env, 0);
1.1       root     2838: #if 0
1.1.1.5   root     2839:         {
                   2840:             int i;
                   2841:             uint8_t *ptr;
                   2842: 
1.1.1.6 ! root     2843:             qemu_log("       code=");
1.1.1.5   root     2844:             ptr = (uint8_t *)env->pc;
                   2845:             for(i = 0; i < 16; i++) {
1.1.1.6 ! root     2846:                 qemu_log(" %02x", ldub(ptr + i));
1.1.1.5   root     2847:             }
1.1.1.6 ! root     2848:             qemu_log("\n");
1.1.1.5   root     2849:         }
1.1       root     2850: #endif
1.1.1.5   root     2851:         count++;
1.1       root     2852:     }
                   2853: #endif
1.1.1.5   root     2854: #if !defined(CONFIG_USER_ONLY)
1.1.1.6 ! root     2855:     if (env->tl >= env->maxtl) {
        !          2856:         cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
        !          2857:                   " Error state", env->exception_index, env->tl, env->maxtl);
1.1.1.5   root     2858:         return;
1.1       root     2859:     }
                   2860: #endif
1.1.1.6 ! root     2861:     if (env->tl < env->maxtl - 1) {
1.1.1.5   root     2862:         env->tl++;
1.1       root     2863:     } else {
1.1.1.5   root     2864:         env->pstate |= PS_RED;
1.1.1.6 ! root     2865:         if (env->tl < env->maxtl)
1.1.1.5   root     2866:             env->tl++;
1.1       root     2867:     }
1.1.1.6 ! root     2868:     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
        !          2869:     env->tsptr->tstate = ((uint64_t)GET_CCR(env) << 32) |
        !          2870:         ((env->asi & 0xff) << 24) | ((env->pstate & 0xf3f) << 8) |
        !          2871:         GET_CWP64(env);
        !          2872:     env->tsptr->tpc = env->pc;
        !          2873:     env->tsptr->tnpc = env->npc;
        !          2874:     env->tsptr->tt = intno;
        !          2875:     if (!(env->def->features & CPU_FEATURE_GL)) {
        !          2876:         switch (intno) {
        !          2877:         case TT_IVEC:
        !          2878:             change_pstate(PS_PEF | PS_PRIV | PS_IG);
        !          2879:             break;
        !          2880:         case TT_TFAULT:
        !          2881:         case TT_TMISS:
        !          2882:         case TT_DFAULT:
        !          2883:         case TT_DMISS:
        !          2884:         case TT_DPROT:
        !          2885:             change_pstate(PS_PEF | PS_PRIV | PS_MG);
        !          2886:             break;
        !          2887:         default:
        !          2888:             change_pstate(PS_PEF | PS_PRIV | PS_AG);
        !          2889:             break;
        !          2890:         }
        !          2891:     }
        !          2892:     if (intno == TT_CLRWIN)
        !          2893:         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - 1));
        !          2894:     else if ((intno & 0x1c0) == TT_SPILL)
        !          2895:         cpu_set_cwp(env, cpu_cwp_dec(env, env->cwp - env->cansave - 2));
        !          2896:     else if ((intno & 0x1c0) == TT_FILL)
        !          2897:         cpu_set_cwp(env, cpu_cwp_inc(env, env->cwp + 1));
        !          2898:     env->tbr &= ~0x7fffULL;
        !          2899:     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
1.1       root     2900:     env->pc = env->tbr;
                   2901:     env->npc = env->pc + 4;
                   2902:     env->exception_index = 0;
                   2903: }
                   2904: #else
1.1.1.5   root     2905: #ifdef DEBUG_PCALL
                   2906: static const char * const excp_names[0x80] = {
                   2907:     [TT_TFAULT] = "Instruction Access Fault",
                   2908:     [TT_ILL_INSN] = "Illegal Instruction",
                   2909:     [TT_PRIV_INSN] = "Privileged Instruction",
                   2910:     [TT_NFPU_INSN] = "FPU Disabled",
                   2911:     [TT_WIN_OVF] = "Window Overflow",
                   2912:     [TT_WIN_UNF] = "Window Underflow",
                   2913:     [TT_UNALIGNED] = "Unaligned Memory Access",
                   2914:     [TT_FP_EXCP] = "FPU Exception",
                   2915:     [TT_DFAULT] = "Data Access Fault",
                   2916:     [TT_TOVF] = "Tag Overflow",
                   2917:     [TT_EXTINT | 0x1] = "External Interrupt 1",
                   2918:     [TT_EXTINT | 0x2] = "External Interrupt 2",
                   2919:     [TT_EXTINT | 0x3] = "External Interrupt 3",
                   2920:     [TT_EXTINT | 0x4] = "External Interrupt 4",
                   2921:     [TT_EXTINT | 0x5] = "External Interrupt 5",
                   2922:     [TT_EXTINT | 0x6] = "External Interrupt 6",
                   2923:     [TT_EXTINT | 0x7] = "External Interrupt 7",
                   2924:     [TT_EXTINT | 0x8] = "External Interrupt 8",
                   2925:     [TT_EXTINT | 0x9] = "External Interrupt 9",
                   2926:     [TT_EXTINT | 0xa] = "External Interrupt 10",
                   2927:     [TT_EXTINT | 0xb] = "External Interrupt 11",
                   2928:     [TT_EXTINT | 0xc] = "External Interrupt 12",
                   2929:     [TT_EXTINT | 0xd] = "External Interrupt 13",
                   2930:     [TT_EXTINT | 0xe] = "External Interrupt 14",
                   2931:     [TT_EXTINT | 0xf] = "External Interrupt 15",
                   2932:     [TT_TOVF] = "Tag Overflow",
                   2933:     [TT_CODE_ACCESS] = "Instruction Access Error",
                   2934:     [TT_DATA_ACCESS] = "Data Access Error",
                   2935:     [TT_DIV_ZERO] = "Division By Zero",
                   2936:     [TT_NCP_INSN] = "Coprocessor Disabled",
                   2937: };
                   2938: #endif
                   2939: 
1.1.1.6 ! root     2940: void do_interrupt(CPUState *env)
1.1       root     2941: {
1.1.1.6 ! root     2942:     int cwp, intno = env->exception_index;
1.1       root     2943: 
                   2944: #ifdef DEBUG_PCALL
1.1.1.6 ! root     2945:     if (qemu_loglevel_mask(CPU_LOG_INT)) {
1.1.1.5   root     2946:         static int count;
                   2947:         const char *name;
                   2948: 
                   2949:         if (intno < 0 || intno >= 0x100)
                   2950:             name = "Unknown";
                   2951:         else if (intno >= 0x80)
                   2952:             name = "Trap Instruction";
                   2953:         else {
                   2954:             name = excp_names[intno];
                   2955:             if (!name)
                   2956:                 name = "Unknown";
                   2957:         }
                   2958: 
1.1.1.6 ! root     2959:         qemu_log("%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
1.1.1.5   root     2960:                 count, name, intno,
1.1       root     2961:                 env->pc,
                   2962:                 env->npc, env->regwptr[6]);
1.1.1.6 ! root     2963:         log_cpu_state(env, 0);
1.1       root     2964: #if 0
1.1.1.5   root     2965:         {
                   2966:             int i;
                   2967:             uint8_t *ptr;
                   2968: 
1.1.1.6 ! root     2969:             qemu_log("       code=");
1.1.1.5   root     2970:             ptr = (uint8_t *)env->pc;
                   2971:             for(i = 0; i < 16; i++) {
1.1.1.6 ! root     2972:                 qemu_log(" %02x", ldub(ptr + i));
1.1.1.5   root     2973:             }
1.1.1.6 ! root     2974:             qemu_log("\n");
1.1.1.5   root     2975:         }
1.1       root     2976: #endif
1.1.1.5   root     2977:         count++;
1.1       root     2978:     }
                   2979: #endif
1.1.1.5   root     2980: #if !defined(CONFIG_USER_ONLY)
1.1       root     2981:     if (env->psret == 0) {
1.1.1.6 ! root     2982:         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
        !          2983:                   env->exception_index);
1.1.1.5   root     2984:         return;
1.1       root     2985:     }
                   2986: #endif
                   2987:     env->psret = 0;
1.1.1.6 ! root     2988:     cwp = cpu_cwp_dec(env, env->cwp - 1);
        !          2989:     cpu_set_cwp(env, cwp);
1.1       root     2990:     env->regwptr[9] = env->pc;
                   2991:     env->regwptr[10] = env->npc;
                   2992:     env->psrps = env->psrs;
                   2993:     env->psrs = 1;
                   2994:     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
                   2995:     env->pc = env->tbr;
                   2996:     env->npc = env->pc + 4;
                   2997:     env->exception_index = 0;
                   2998: }
                   2999: #endif
                   3000: 
1.1.1.5   root     3001: #if !defined(CONFIG_USER_ONLY)
                   3002: 
                   3003: static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
                   3004:                                 void *retaddr);
1.1       root     3005: 
                   3006: #define MMUSUFFIX _mmu
1.1.1.5   root     3007: #define ALIGNED_ONLY
1.1       root     3008: 
                   3009: #define SHIFT 0
                   3010: #include "softmmu_template.h"
                   3011: 
                   3012: #define SHIFT 1
                   3013: #include "softmmu_template.h"
                   3014: 
                   3015: #define SHIFT 2
                   3016: #include "softmmu_template.h"
                   3017: 
                   3018: #define SHIFT 3
                   3019: #include "softmmu_template.h"
                   3020: 
1.1.1.6 ! root     3021: /* XXX: make it generic ? */
        !          3022: static void cpu_restore_state2(void *retaddr)
        !          3023: {
        !          3024:     TranslationBlock *tb;
        !          3025:     unsigned long pc;
        !          3026: 
        !          3027:     if (retaddr) {
        !          3028:         /* now we have a real cpu fault */
        !          3029:         pc = (unsigned long)retaddr;
        !          3030:         tb = tb_find_pc(pc);
        !          3031:         if (tb) {
        !          3032:             /* the PC is inside the translated code. It means that we have
        !          3033:                a virtual CPU fault */
        !          3034:             cpu_restore_state(tb, env, pc, (void *)(long)env->cond);
        !          3035:         }
        !          3036:     }
        !          3037: }
        !          3038: 
1.1.1.5   root     3039: static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
                   3040:                                 void *retaddr)
                   3041: {
                   3042: #ifdef DEBUG_UNALIGNED
1.1.1.6 ! root     3043:     printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
        !          3044:            "\n", addr, env->pc);
1.1.1.5   root     3045: #endif
1.1.1.6 ! root     3046:     cpu_restore_state2(retaddr);
1.1.1.5   root     3047:     raise_exception(TT_UNALIGNED);
                   3048: }
1.1       root     3049: 
                   3050: /* try to fill the TLB and return an exception if error. If retaddr is
                   3051:    NULL, it means that the function was called in C code (i.e. not
                   3052:    from generated code or from helper.c) */
                   3053: /* XXX: fix it to restore all registers */
1.1.1.5   root     3054: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1       root     3055: {
                   3056:     int ret;
                   3057:     CPUState *saved_env;
                   3058: 
                   3059:     /* XXX: hack to restore env in all cases, even if not called from
                   3060:        generated code */
                   3061:     saved_env = env;
                   3062:     env = cpu_single_env;
                   3063: 
1.1.1.5   root     3064:     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1       root     3065:     if (ret) {
1.1.1.6 ! root     3066:         cpu_restore_state2(retaddr);
1.1       root     3067:         cpu_loop_exit();
                   3068:     }
                   3069:     env = saved_env;
                   3070: }
                   3071: 
                   3072: #endif
1.1.1.5   root     3073: 
                   3074: #ifndef TARGET_SPARC64
                   3075: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.6 ! root     3076:                           int is_asi, int size)
1.1.1.5   root     3077: {
                   3078:     CPUState *saved_env;
                   3079: 
                   3080:     /* XXX: hack to restore env in all cases, even if not called from
                   3081:        generated code */
                   3082:     saved_env = env;
                   3083:     env = cpu_single_env;
                   3084: #ifdef DEBUG_UNASSIGNED
                   3085:     if (is_asi)
1.1.1.6 ! root     3086:         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
        !          3087:                " asi 0x%02x from " TARGET_FMT_lx "\n",
        !          3088:                is_exec ? "exec" : is_write ? "write" : "read", size,
        !          3089:                size == 1 ? "" : "s", addr, is_asi, env->pc);
1.1.1.5   root     3090:     else
1.1.1.6 ! root     3091:         printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx
        !          3092:                " from " TARGET_FMT_lx "\n",
        !          3093:                is_exec ? "exec" : is_write ? "write" : "read", size,
        !          3094:                size == 1 ? "" : "s", addr, env->pc);
1.1.1.5   root     3095: #endif
                   3096:     if (env->mmuregs[3]) /* Fault status register */
                   3097:         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
                   3098:     if (is_asi)
                   3099:         env->mmuregs[3] |= 1 << 16;
                   3100:     if (env->psrs)
                   3101:         env->mmuregs[3] |= 1 << 5;
                   3102:     if (is_exec)
                   3103:         env->mmuregs[3] |= 1 << 6;
                   3104:     if (is_write)
                   3105:         env->mmuregs[3] |= 1 << 7;
                   3106:     env->mmuregs[3] |= (5 << 2) | 2;
                   3107:     env->mmuregs[4] = addr; /* Fault address register */
                   3108:     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
                   3109:         if (is_exec)
                   3110:             raise_exception(TT_CODE_ACCESS);
                   3111:         else
                   3112:             raise_exception(TT_DATA_ACCESS);
                   3113:     }
                   3114:     env = saved_env;
                   3115: }
                   3116: #else
                   3117: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
1.1.1.6 ! root     3118:                           int is_asi, int size)
1.1.1.5   root     3119: {
                   3120: #ifdef DEBUG_UNASSIGNED
                   3121:     CPUState *saved_env;
                   3122: 
                   3123:     /* XXX: hack to restore env in all cases, even if not called from
                   3124:        generated code */
                   3125:     saved_env = env;
                   3126:     env = cpu_single_env;
1.1.1.6 ! root     3127:     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
        !          3128:            "\n", addr, env->pc);
1.1.1.5   root     3129:     env = saved_env;
                   3130: #endif
                   3131:     if (is_exec)
                   3132:         raise_exception(TT_CODE_ACCESS);
                   3133:     else
                   3134:         raise_exception(TT_DATA_ACCESS);
                   3135: }
                   3136: #endif
                   3137: 
1.1.1.6 ! root     3138: #ifdef TARGET_SPARC64
        !          3139: void helper_tick_set_count(void *opaque, uint64_t count)
        !          3140: {
        !          3141: #if !defined(CONFIG_USER_ONLY)
        !          3142:     cpu_tick_set_count(opaque, count);
        !          3143: #endif
        !          3144: }
        !          3145: 
        !          3146: uint64_t helper_tick_get_count(void *opaque)
        !          3147: {
        !          3148: #if !defined(CONFIG_USER_ONLY)
        !          3149:     return cpu_tick_get_count(opaque);
        !          3150: #else
        !          3151:     return 0;
        !          3152: #endif
        !          3153: }
        !          3154: 
        !          3155: void helper_tick_set_limit(void *opaque, uint64_t limit)
        !          3156: {
        !          3157: #if !defined(CONFIG_USER_ONLY)
        !          3158:     cpu_tick_set_limit(opaque, limit);
        !          3159: #endif
        !          3160: }
        !          3161: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.