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

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

unix.superglobalmegacorp.com

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