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

1.1       root        1: #include "exec.h"
1.1.1.5 ! root        2: #include "host-utils.h"
1.1       root        3: 
                      4: //#define DEBUG_PCALL
                      5: //#define DEBUG_MMU
1.1.1.5 ! root        6: //#define DEBUG_MXCC
        !             7: //#define DEBUG_UNALIGNED
        !             8: //#define DEBUG_UNASSIGNED
        !             9: //#define DEBUG_ASI
        !            10: 
        !            11: #ifdef DEBUG_MMU
        !            12: #define DPRINTF_MMU(fmt, args...) \
        !            13: do { printf("MMU: " fmt , ##args); } while (0)
        !            14: #else
        !            15: #define DPRINTF_MMU(fmt, args...)
        !            16: #endif
        !            17: 
        !            18: #ifdef DEBUG_MXCC
        !            19: #define DPRINTF_MXCC(fmt, args...) \
        !            20: do { printf("MXCC: " fmt , ##args); } while (0)
        !            21: #else
        !            22: #define DPRINTF_MXCC(fmt, args...)
        !            23: #endif
        !            24: 
        !            25: #ifdef DEBUG_ASI
        !            26: #define DPRINTF_ASI(fmt, args...) \
        !            27: do { printf("ASI: " fmt , ##args); } while (0)
        !            28: #else
        !            29: #define DPRINTF_ASI(fmt, args...)
        !            30: #endif
1.1       root       31: 
                     32: void raise_exception(int tt)
                     33: {
                     34:     env->exception_index = tt;
                     35:     cpu_loop_exit();
1.1.1.5 ! root       36: }
        !            37: 
        !            38: void check_ieee_exceptions()
        !            39: {
        !            40:      T0 = get_float_exception_flags(&env->fp_status);
        !            41:      if (T0)
        !            42:      {
        !            43:         /* Copy IEEE 754 flags into FSR */
        !            44:         if (T0 & float_flag_invalid)
        !            45:             env->fsr |= FSR_NVC;
        !            46:         if (T0 & float_flag_overflow)
        !            47:             env->fsr |= FSR_OFC;
        !            48:         if (T0 & float_flag_underflow)
        !            49:             env->fsr |= FSR_UFC;
        !            50:         if (T0 & float_flag_divbyzero)
        !            51:             env->fsr |= FSR_DZC;
        !            52:         if (T0 & float_flag_inexact)
        !            53:             env->fsr |= FSR_NXC;
        !            54: 
        !            55:         if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23))
        !            56:         {
        !            57:             /* Unmasked exception, generate a trap */
        !            58:             env->fsr |= FSR_FTT_IEEE_EXCP;
        !            59:             raise_exception(TT_FP_EXCP);
        !            60:         }
        !            61:         else
        !            62:         {
        !            63:             /* Accumulate exceptions */
        !            64:             env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
        !            65:         }
        !            66:      }
        !            67: }
1.1       root       68: 
                     69: #ifdef USE_INT_TO_FLOAT_HELPERS
                     70: void do_fitos(void)
                     71: {
1.1.1.5 ! root       72:     set_float_exception_flags(0, &env->fp_status);
1.1.1.4   root       73:     FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);
1.1.1.5 ! root       74:     check_ieee_exceptions();
1.1       root       75: }
                     76: 
                     77: void do_fitod(void)
                     78: {
1.1.1.4   root       79:     DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);
1.1       root       80: }
1.1.1.5 ! root       81: 
        !            82: #if defined(CONFIG_USER_ONLY)
        !            83: void do_fitoq(void)
        !            84: {
        !            85:     QT0 = int32_to_float128(*((int32_t *)&FT1), &env->fp_status);
        !            86: }
        !            87: #endif
        !            88: 
        !            89: #ifdef TARGET_SPARC64
        !            90: void do_fxtos(void)
        !            91: {
        !            92:     set_float_exception_flags(0, &env->fp_status);
        !            93:     FT0 = int64_to_float32(*((int64_t *)&DT1), &env->fp_status);
        !            94:     check_ieee_exceptions();
        !            95: }
        !            96: 
        !            97: void do_fxtod(void)
        !            98: {
        !            99:     set_float_exception_flags(0, &env->fp_status);
        !           100:     DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status);
        !           101:     check_ieee_exceptions();
        !           102: }
        !           103: 
        !           104: #if defined(CONFIG_USER_ONLY)
        !           105: void do_fxtoq(void)
        !           106: {
        !           107:     set_float_exception_flags(0, &env->fp_status);
        !           108:     QT0 = int64_to_float128(*((int32_t *)&DT1), &env->fp_status);
        !           109:     check_ieee_exceptions();
        !           110: }
        !           111: #endif
        !           112: #endif
1.1       root      113: #endif
                    114: 
                    115: void do_fabss(void)
                    116: {
                    117:     FT0 = float32_abs(FT1);
                    118: }
                    119: 
                    120: #ifdef TARGET_SPARC64
                    121: void do_fabsd(void)
                    122: {
                    123:     DT0 = float64_abs(DT1);
                    124: }
1.1.1.5 ! root      125: 
        !           126: #if defined(CONFIG_USER_ONLY)
        !           127: void do_fabsq(void)
        !           128: {
        !           129:     QT0 = float128_abs(QT1);
        !           130: }
        !           131: #endif
1.1       root      132: #endif
                    133: 
                    134: void do_fsqrts(void)
                    135: {
1.1.1.5 ! root      136:     set_float_exception_flags(0, &env->fp_status);
1.1       root      137:     FT0 = float32_sqrt(FT1, &env->fp_status);
1.1.1.5 ! root      138:     check_ieee_exceptions();
1.1       root      139: }
                    140: 
                    141: void do_fsqrtd(void)
                    142: {
1.1.1.5 ! root      143:     set_float_exception_flags(0, &env->fp_status);
1.1       root      144:     DT0 = float64_sqrt(DT1, &env->fp_status);
1.1.1.5 ! root      145:     check_ieee_exceptions();
1.1       root      146: }
                    147: 
1.1.1.5 ! root      148: #if defined(CONFIG_USER_ONLY)
        !           149: void do_fsqrtq(void)
        !           150: {
        !           151:     set_float_exception_flags(0, &env->fp_status);
        !           152:     QT0 = float128_sqrt(QT1, &env->fp_status);
        !           153:     check_ieee_exceptions();
        !           154: }
        !           155: #endif
        !           156: 
        !           157: #define GEN_FCMP(name, size, reg1, reg2, FS, TRAP)                      \
1.1.1.3   root      158:     void glue(do_, name) (void)                                         \
                    159:     {                                                                   \
                    160:         env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \
                    161:         switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \
                    162:         case float_relation_unordered:                                  \
                    163:             T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \
1.1.1.5 ! root      164:             if ((env->fsr & FSR_NVM) || TRAP) {                         \
1.1.1.3   root      165:                 env->fsr |= T0;                                         \
1.1.1.5 ! root      166:                 env->fsr |= FSR_NVC;                                    \
        !           167:                 env->fsr |= FSR_FTT_IEEE_EXCP;                          \
1.1.1.3   root      168:                 raise_exception(TT_FP_EXCP);                            \
                    169:             } else {                                                    \
                    170:                 env->fsr |= FSR_NVA;                                    \
                    171:             }                                                           \
                    172:             break;                                                      \
                    173:         case float_relation_less:                                       \
                    174:             T0 = FSR_FCC0 << FS;                                        \
                    175:             break;                                                      \
                    176:         case float_relation_greater:                                    \
                    177:             T0 = FSR_FCC1 << FS;                                        \
                    178:             break;                                                      \
                    179:         default:                                                        \
                    180:             T0 = 0;                                                     \
                    181:             break;                                                      \
                    182:         }                                                               \
                    183:         env->fsr |= T0;                                                 \
1.1       root      184:     }
                    185: 
1.1.1.5 ! root      186: GEN_FCMP(fcmps, float32, FT0, FT1, 0, 0);
        !           187: GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0);
        !           188: 
        !           189: GEN_FCMP(fcmpes, float32, FT0, FT1, 0, 1);
        !           190: GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1);
        !           191: 
        !           192: #ifdef CONFIG_USER_ONLY
        !           193: GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
        !           194: GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
        !           195: #endif
1.1       root      196: 
                    197: #ifdef TARGET_SPARC64
1.1.1.5 ! root      198: GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22, 0);
        !           199: GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0);
1.1       root      200: 
1.1.1.5 ! root      201: GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24, 0);
        !           202: GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0);
1.1       root      203: 
1.1.1.5 ! root      204: GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26, 0);
        !           205: GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0);
        !           206: 
        !           207: GEN_FCMP(fcmpes_fcc1, float32, FT0, FT1, 22, 1);
        !           208: GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1);
        !           209: 
        !           210: GEN_FCMP(fcmpes_fcc2, float32, FT0, FT1, 24, 1);
        !           211: GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1);
        !           212: 
        !           213: GEN_FCMP(fcmpes_fcc3, float32, FT0, FT1, 26, 1);
        !           214: GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1);
        !           215: #ifdef CONFIG_USER_ONLY
        !           216: GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
        !           217: GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
        !           218: GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
        !           219: GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
        !           220: GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
        !           221: GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
        !           222: #endif
1.1       root      223: #endif
                    224: 
1.1.1.5 ! root      225: #ifndef TARGET_SPARC64
        !           226: #ifndef CONFIG_USER_ONLY
        !           227: 
        !           228: #ifdef DEBUG_MXCC
        !           229: static void dump_mxcc(CPUState *env)
1.1.1.2   root      230: {
1.1.1.5 ! root      231:     printf("mxccdata: %016llx %016llx %016llx %016llx\n",
        !           232:         env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]);
        !           233:     printf("mxccregs: %016llx %016llx %016llx %016llx\n"
        !           234:            "          %016llx %016llx %016llx %016llx\n",
        !           235:         env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3],
        !           236:         env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]);
1.1.1.2   root      237: }
1.1.1.5 ! root      238: #endif
1.1.1.2   root      239: 
1.1.1.5 ! root      240: #ifdef DEBUG_ASI
        !           241: static void dump_asi(const char * txt, uint32_t addr, int asi, int size,
        !           242:                      uint32_t r1, uint32_t r2)
        !           243: {
        !           244:     switch (size)
        !           245:     {
        !           246:     case 1:
        !           247:         DPRINTF_ASI("%s %08x asi 0x%02x = %02x\n", txt, addr, asi, r1 & 0xff);
        !           248:         break;
        !           249:     case 2:
        !           250:         DPRINTF_ASI("%s %08x asi 0x%02x = %04x\n", txt, addr, asi, r1 & 0xffff);
        !           251:         break;
        !           252:     case 4:
        !           253:         DPRINTF_ASI("%s %08x asi 0x%02x = %08x\n", txt, addr, asi, r1);
        !           254:         break;
        !           255:     case 8:
        !           256:         DPRINTF_ASI("%s %08x asi 0x%02x = %016llx\n", txt, addr, asi,
        !           257:                     r2 | ((uint64_t)r1 << 32));
        !           258:         break;
        !           259:     }
1.1.1.2   root      260: }
1.1.1.5 ! root      261: #endif
        !           262: 
1.1       root      263: void helper_ld_asi(int asi, int size, int sign)
                    264: {
                    265:     uint32_t ret = 0;
1.1.1.5 ! root      266:     uint64_t tmp;
        !           267: #if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
        !           268:     uint32_t last_T0 = T0;
        !           269: #endif
1.1       root      270: 
                    271:     switch (asi) {
1.1.1.5 ! root      272:     case 2: /* SuperSparc MXCC registers */
        !           273:         switch (T0) {
        !           274:         case 0x01c00a00: /* MXCC control register */
        !           275:             if (size == 8) {
        !           276:                 ret = env->mxccregs[3] >> 32;
        !           277:                 T0 = env->mxccregs[3];
        !           278:             } else
        !           279:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           280:             break;
        !           281:         case 0x01c00a04: /* MXCC control register */
        !           282:             if (size == 4)
        !           283:                 ret = env->mxccregs[3];
        !           284:             else
        !           285:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           286:             break;
        !           287:         case 0x01c00c00: /* Module reset register */
        !           288:             if (size == 8) {
        !           289:                 ret = env->mxccregs[5] >> 32;
        !           290:                 T0 = env->mxccregs[5];
        !           291:                 // should we do something here?
        !           292:             } else
        !           293:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           294:             break;
        !           295:         case 0x01c00f00: /* MBus port address register */
        !           296:             if (size == 8) {
        !           297:                 ret = env->mxccregs[7] >> 32;
        !           298:                 T0 = env->mxccregs[7];
        !           299:             } else
        !           300:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           301:             break;
        !           302:         default:
        !           303:             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
        !           304:             break;
        !           305:         }
        !           306:         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x,"
        !           307:                      "T0 = %08x\n", asi, size, sign, last_T0, ret, T0);
        !           308: #ifdef DEBUG_MXCC
        !           309:         dump_mxcc(env);
        !           310: #endif
        !           311:         break;
1.1       root      312:     case 3: /* MMU probe */
1.1.1.5 ! root      313:         {
        !           314:             int mmulev;
1.1       root      315: 
1.1.1.5 ! root      316:             mmulev = (T0 >> 8) & 15;
        !           317:             if (mmulev > 4)
        !           318:                 ret = 0;
        !           319:             else {
        !           320:                 ret = mmu_probe(env, T0, mmulev);
        !           321:                 //bswap32s(&ret);
        !           322:             }
        !           323:             DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
        !           324:         }
        !           325:         break;
1.1       root      326:     case 4: /* read MMU regs */
1.1.1.5 ! root      327:         {
        !           328:             int reg = (T0 >> 8) & 0x1f;
        !           329: 
        !           330:             ret = env->mmuregs[reg];
        !           331:             if (reg == 3) /* Fault status cleared on read */
        !           332:                 env->mmuregs[3] = 0;
        !           333:             else if (reg == 0x13) /* Fault status read */
        !           334:                 ret = env->mmuregs[3];
        !           335:             else if (reg == 0x14) /* Fault address read */
        !           336:                 ret = env->mmuregs[4];
        !           337:             DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
        !           338:         }
        !           339:         break;
        !           340:     case 5: // Turbosparc ITLB Diagnostic
        !           341:     case 6: // Turbosparc DTLB Diagnostic
        !           342:     case 7: // Turbosparc IOTLB Diagnostic
        !           343:         break;
        !           344:     case 9: /* Supervisor code access */
        !           345:         switch(size) {
        !           346:         case 1:
        !           347:             ret = ldub_code(T0);
        !           348:             break;
        !           349:         case 2:
        !           350:             ret = lduw_code(T0 & ~1);
        !           351:             break;
        !           352:         default:
        !           353:         case 4:
        !           354:             ret = ldl_code(T0 & ~3);
        !           355:             break;
        !           356:         case 8:
        !           357:             tmp = ldq_code(T0 & ~7);
        !           358:             ret = tmp >> 32;
        !           359:             T0 = tmp;
        !           360:             break;
        !           361:         }
        !           362:         break;
        !           363:     case 0xa: /* User data access */
        !           364:         switch(size) {
        !           365:         case 1:
        !           366:             ret = ldub_user(T0);
        !           367:             break;
        !           368:         case 2:
        !           369:             ret = lduw_user(T0 & ~1);
        !           370:             break;
        !           371:         default:
        !           372:         case 4:
        !           373:             ret = ldl_user(T0 & ~3);
        !           374:             break;
        !           375:         case 8:
        !           376:             tmp = ldq_user(T0 & ~7);
        !           377:             ret = tmp >> 32;
        !           378:             T0 = tmp;
        !           379:             break;
        !           380:         }
        !           381:         break;
        !           382:     case 0xb: /* Supervisor data access */
        !           383:         switch(size) {
        !           384:         case 1:
        !           385:             ret = ldub_kernel(T0);
        !           386:             break;
        !           387:         case 2:
        !           388:             ret = lduw_kernel(T0 & ~1);
        !           389:             break;
        !           390:         default:
        !           391:         case 4:
        !           392:             ret = ldl_kernel(T0 & ~3);
        !           393:             break;
        !           394:         case 8:
        !           395:             tmp = ldq_kernel(T0 & ~7);
        !           396:             ret = tmp >> 32;
        !           397:             T0 = tmp;
        !           398:             break;
        !           399:         }
        !           400:         break;
        !           401:     case 0xc: /* I-cache tag */
        !           402:     case 0xd: /* I-cache data */
        !           403:     case 0xe: /* D-cache tag */
        !           404:     case 0xf: /* D-cache data */
        !           405:         break;
        !           406:     case 0x20: /* MMU passthrough */
1.1.1.2   root      407:         switch(size) {
                    408:         case 1:
                    409:             ret = ldub_phys(T0);
                    410:             break;
                    411:         case 2:
                    412:             ret = lduw_phys(T0 & ~1);
                    413:             break;
                    414:         default:
                    415:         case 4:
                    416:             ret = ldl_phys(T0 & ~3);
                    417:             break;
                    418:         case 8:
1.1.1.5 ! root      419:             tmp = ldq_phys(T0 & ~7);
        !           420:             ret = tmp >> 32;
        !           421:             T0 = tmp;
        !           422:             break;
1.1.1.2   root      423:         }
1.1.1.5 ! root      424:         break;
        !           425:     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
        !           426:         switch(size) {
        !           427:         case 1:
        !           428:             ret = ldub_phys((target_phys_addr_t)T0
        !           429:                             | ((target_phys_addr_t)(asi & 0xf) << 32));
        !           430:             break;
        !           431:         case 2:
        !           432:             ret = lduw_phys((target_phys_addr_t)(T0 & ~1)
        !           433:                             | ((target_phys_addr_t)(asi & 0xf) << 32));
        !           434:             break;
        !           435:         default:
        !           436:         case 4:
        !           437:             ret = ldl_phys((target_phys_addr_t)(T0 & ~3)
        !           438:                            | ((target_phys_addr_t)(asi & 0xf) << 32));
        !           439:             break;
        !           440:         case 8:
        !           441:             tmp = ldq_phys((target_phys_addr_t)(T0 & ~7)
        !           442:                            | ((target_phys_addr_t)(asi & 0xf) << 32));
        !           443:             ret = tmp >> 32;
        !           444:             T0 = tmp;
        !           445:             break;
        !           446:         }
        !           447:         break;
        !           448:     case 0x30: // Turbosparc secondary cache diagnostic
        !           449:     case 0x31: // Turbosparc RAM snoop
        !           450:     case 0x32: // Turbosparc page table descriptor diagnostic
        !           451:     case 0x39: /* data cache diagnostic register */
        !           452:         ret = 0;
        !           453:         break;
        !           454:     case 8: /* User code access, XXX */
1.1       root      455:     default:
1.1.1.5 ! root      456:         do_unassigned_access(T0, 0, 0, asi);
        !           457:         ret = 0;
        !           458:         break;
1.1       root      459:     }
1.1.1.5 ! root      460:     if (sign) {
        !           461:         switch(size) {
        !           462:         case 1:
        !           463:             T1 = (int8_t) ret;
        !           464:             break;
        !           465:         case 2:
        !           466:             T1 = (int16_t) ret;
        !           467:             break;
        !           468:         default:
        !           469:             T1 = ret;
        !           470:             break;
        !           471:         }
        !           472:     }
        !           473:     else
        !           474:         T1 = ret;
        !           475: #ifdef DEBUG_ASI
        !           476:     dump_asi("read ", last_T0, asi, size, T1, T0);
        !           477: #endif
1.1       root      478: }
                    479: 
1.1.1.5 ! root      480: void helper_st_asi(int asi, int size)
1.1       root      481: {
                    482:     switch(asi) {
1.1.1.5 ! root      483:     case 2: /* SuperSparc MXCC registers */
        !           484:         switch (T0) {
        !           485:         case 0x01c00000: /* MXCC stream data register 0 */
        !           486:             if (size == 8)
        !           487:                 env->mxccdata[0] = ((uint64_t)T1 << 32) | T2;
        !           488:             else
        !           489:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           490:             break;
        !           491:         case 0x01c00008: /* MXCC stream data register 1 */
        !           492:             if (size == 8)
        !           493:                 env->mxccdata[1] = ((uint64_t)T1 << 32) | T2;
        !           494:             else
        !           495:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           496:             break;
        !           497:         case 0x01c00010: /* MXCC stream data register 2 */
        !           498:             if (size == 8)
        !           499:                 env->mxccdata[2] = ((uint64_t)T1 << 32) | T2;
        !           500:             else
        !           501:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           502:             break;
        !           503:         case 0x01c00018: /* MXCC stream data register 3 */
        !           504:             if (size == 8)
        !           505:                 env->mxccdata[3] = ((uint64_t)T1 << 32) | T2;
        !           506:             else
        !           507:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           508:             break;
        !           509:         case 0x01c00100: /* MXCC stream source */
        !           510:             if (size == 8)
        !           511:                 env->mxccregs[0] = ((uint64_t)T1 << 32) | T2;
        !           512:             else
        !           513:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           514:             env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  0);
        !           515:             env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +  8);
        !           516:             env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16);
        !           517:             env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24);
        !           518:             break;
        !           519:         case 0x01c00200: /* MXCC stream destination */
        !           520:             if (size == 8)
        !           521:                 env->mxccregs[1] = ((uint64_t)T1 << 32) | T2;
        !           522:             else
        !           523:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           524:             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0, env->mxccdata[0]);
        !           525:             stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8, env->mxccdata[1]);
        !           526:             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]);
        !           527:             stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]);
        !           528:             break;
        !           529:         case 0x01c00a00: /* MXCC control register */
        !           530:             if (size == 8)
        !           531:                 env->mxccregs[3] = ((uint64_t)T1 << 32) | T2;
        !           532:             else
        !           533:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           534:             break;
        !           535:         case 0x01c00a04: /* MXCC control register */
        !           536:             if (size == 4)
        !           537:                 env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL) | T1;
        !           538:             else
        !           539:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           540:             break;
        !           541:         case 0x01c00e00: /* MXCC error register  */
        !           542:             // writing a 1 bit clears the error
        !           543:             if (size == 8)
        !           544:                 env->mxccregs[6] &= ~(((uint64_t)T1 << 32) | T2);
        !           545:             else
        !           546:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           547:             break;
        !           548:         case 0x01c00f00: /* MBus port address register */
        !           549:             if (size == 8)
        !           550:                 env->mxccregs[7] = ((uint64_t)T1 << 32) | T2;
        !           551:             else
        !           552:                 DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size);
        !           553:             break;
        !           554:         default:
        !           555:             DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size);
        !           556:             break;
        !           557:         }
        !           558:         DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1);
        !           559: #ifdef DEBUG_MXCC
        !           560:         dump_mxcc(env);
        !           561: #endif
        !           562:         break;
1.1       root      563:     case 3: /* MMU flush */
1.1.1.5 ! root      564:         {
        !           565:             int mmulev;
1.1       root      566: 
1.1.1.5 ! root      567:             mmulev = (T0 >> 8) & 15;
        !           568:             DPRINTF_MMU("mmu flush level %d\n", mmulev);
        !           569:             switch (mmulev) {
        !           570:             case 0: // flush page
        !           571:                 tlb_flush_page(env, T0 & 0xfffff000);
        !           572:                 break;
        !           573:             case 1: // flush segment (256k)
        !           574:             case 2: // flush region (16M)
        !           575:             case 3: // flush context (4G)
        !           576:             case 4: // flush entire
        !           577:                 tlb_flush(env, 1);
        !           578:                 break;
        !           579:             default:
        !           580:                 break;
        !           581:             }
1.1       root      582: #ifdef DEBUG_MMU
1.1.1.5 ! root      583:             dump_mmu(env);
1.1       root      584: #endif
1.1.1.5 ! root      585:         }
        !           586:         break;
1.1       root      587:     case 4: /* write MMU regs */
1.1.1.5 ! root      588:         {
        !           589:             int reg = (T0 >> 8) & 0x1f;
        !           590:             uint32_t oldreg;
        !           591: 
        !           592:             oldreg = env->mmuregs[reg];
1.1       root      593:             switch(reg) {
                    594:             case 0:
1.1.1.5 ! root      595:                 env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |
        !           596:                                     (T1 & 0x00ffffff);
        !           597:                 // Mappings generated during no-fault mode or MMU
        !           598:                 // disabled mode are invalid in normal mode
        !           599:                 if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=
        !           600:                     (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))
1.1       root      601:                     tlb_flush(env, 1);
                    602:                 break;
                    603:             case 2:
1.1.1.5 ! root      604:                 env->mmuregs[reg] = T1;
1.1       root      605:                 if (oldreg != env->mmuregs[reg]) {
                    606:                     /* we flush when the MMU context changes because
                    607:                        QEMU has no MMU context support */
                    608:                     tlb_flush(env, 1);
                    609:                 }
                    610:                 break;
                    611:             case 3:
                    612:             case 4:
                    613:                 break;
1.1.1.5 ! root      614:             case 0x13:
        !           615:                 env->mmuregs[3] = T1;
        !           616:                 break;
        !           617:             case 0x14:
        !           618:                 env->mmuregs[4] = T1;
        !           619:                 break;
1.1       root      620:             default:
1.1.1.5 ! root      621:                 env->mmuregs[reg] = T1;
1.1       root      622:                 break;
                    623:             }
                    624:             if (oldreg != env->mmuregs[reg]) {
1.1.1.5 ! root      625:                 DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
1.1       root      626:             }
1.1.1.5 ! root      627: #ifdef DEBUG_MMU
        !           628:             dump_mmu(env);
1.1       root      629: #endif
1.1.1.5 ! root      630:         }
        !           631:         break;
        !           632:     case 5: // Turbosparc ITLB Diagnostic
        !           633:     case 6: // Turbosparc DTLB Diagnostic
        !           634:     case 7: // Turbosparc IOTLB Diagnostic
        !           635:         break;
        !           636:     case 0xa: /* User data access */
        !           637:         switch(size) {
        !           638:         case 1:
        !           639:             stb_user(T0, T1);
        !           640:             break;
        !           641:         case 2:
        !           642:             stw_user(T0 & ~1, T1);
        !           643:             break;
        !           644:         default:
        !           645:         case 4:
        !           646:             stl_user(T0 & ~3, T1);
        !           647:             break;
        !           648:         case 8:
        !           649:             stq_user(T0 & ~7, ((uint64_t)T1 << 32) | T2);
        !           650:             break;
        !           651:         }
        !           652:         break;
        !           653:     case 0xb: /* Supervisor data access */
        !           654:         switch(size) {
        !           655:         case 1:
        !           656:             stb_kernel(T0, T1);
        !           657:             break;
        !           658:         case 2:
        !           659:             stw_kernel(T0 & ~1, T1);
        !           660:             break;
        !           661:         default:
        !           662:         case 4:
        !           663:             stl_kernel(T0 & ~3, T1);
        !           664:             break;
        !           665:         case 8:
        !           666:             stq_kernel(T0 & ~7, ((uint64_t)T1 << 32) | T2);
        !           667:             break;
        !           668:         }
        !           669:         break;
        !           670:     case 0xc: /* I-cache tag */
        !           671:     case 0xd: /* I-cache data */
        !           672:     case 0xe: /* D-cache tag */
        !           673:     case 0xf: /* D-cache data */
        !           674:     case 0x10: /* I/D-cache flush page */
        !           675:     case 0x11: /* I/D-cache flush segment */
        !           676:     case 0x12: /* I/D-cache flush region */
        !           677:     case 0x13: /* I/D-cache flush context */
        !           678:     case 0x14: /* I/D-cache flush user */
        !           679:         break;
1.1       root      680:     case 0x17: /* Block copy, sta access */
1.1.1.5 ! root      681:         {
        !           682:             // value (T1) = src
        !           683:             // address (T0) = dst
        !           684:             // copy 32 bytes
        !           685:             unsigned int i;
        !           686:             uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
        !           687: 
        !           688:             for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
        !           689:                 temp = ldl_kernel(src);
        !           690:                 stl_kernel(dst, temp);
        !           691:             }
        !           692:         }
        !           693:         break;
1.1       root      694:     case 0x1f: /* Block fill, stda access */
1.1.1.5 ! root      695:         {
        !           696:             // value (T1, T2)
        !           697:             // address (T0) = dst
        !           698:             // fill 32 bytes
        !           699:             unsigned int i;
        !           700:             uint32_t dst = T0 & 7;
        !           701:             uint64_t val;
        !           702: 
        !           703:             val = (((uint64_t)T1) << 32) | T2;
        !           704: 
        !           705:             for (i = 0; i < 32; i += 8, dst += 8)
        !           706:                 stq_kernel(dst, val);
        !           707:         }
        !           708:         break;
        !           709:     case 0x20: /* MMU passthrough */
        !           710:         {
        !           711:             switch(size) {
        !           712:             case 1:
        !           713:                 stb_phys(T0, T1);
        !           714:                 break;
        !           715:             case 2:
        !           716:                 stw_phys(T0 & ~1, T1);
        !           717:                 break;
        !           718:             case 4:
        !           719:             default:
        !           720:                 stl_phys(T0 & ~3, T1);
        !           721:                 break;
        !           722:             case 8:
        !           723:                 stq_phys(T0 & ~7, ((uint64_t)T1 << 32) | T2);
        !           724:                 break;
        !           725:             }
        !           726:         }
        !           727:         break;
        !           728:     case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
        !           729:         {
        !           730:             switch(size) {
        !           731:             case 1:
        !           732:                 stb_phys((target_phys_addr_t)T0
        !           733:                          | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
        !           734:                 break;
        !           735:             case 2:
        !           736:                 stw_phys((target_phys_addr_t)(T0 & ~1)
        !           737:                             | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
        !           738:                 break;
        !           739:             case 4:
        !           740:             default:
        !           741:                 stl_phys((target_phys_addr_t)(T0 & ~3)
        !           742:                            | ((target_phys_addr_t)(asi & 0xf) << 32), T1);
        !           743:                 break;
        !           744:             case 8:
        !           745:                 stq_phys((target_phys_addr_t)(T0 & ~7)
        !           746:                            | ((target_phys_addr_t)(asi & 0xf) << 32),
        !           747:                          ((uint64_t)T1 << 32) | T2);
        !           748:                 break;
        !           749:             }
        !           750:         }
        !           751:         break;
        !           752:     case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic
        !           753:     case 0x31: // store buffer data, Ross RT620 I-cache flush or
        !           754:                // Turbosparc snoop RAM
        !           755:     case 0x32: // store buffer control or Turbosparc page table descriptor diagnostic
        !           756:     case 0x36: /* I-cache flash clear */
        !           757:     case 0x37: /* D-cache flash clear */
        !           758:     case 0x38: /* breakpoint diagnostics */
        !           759:     case 0x4c: /* breakpoint action */
        !           760:         break;
        !           761:     case 8: /* User code access, XXX */
        !           762:     case 9: /* Supervisor code access, XXX */
        !           763:     default:
        !           764:         do_unassigned_access(T0, 1, 0, asi);
        !           765:         break;
        !           766:     }
        !           767: #ifdef DEBUG_ASI
        !           768:     dump_asi("write", T0, asi, size, T1, T2);
        !           769: #endif
        !           770: }
        !           771: 
        !           772: #endif /* CONFIG_USER_ONLY */
        !           773: #else /* TARGET_SPARC64 */
        !           774: 
        !           775: #ifdef CONFIG_USER_ONLY
        !           776: void helper_ld_asi(int asi, int size, int sign)
        !           777: {
        !           778:     uint64_t ret = 0;
        !           779: 
        !           780:     if (asi < 0x80)
        !           781:         raise_exception(TT_PRIV_ACT);
        !           782: 
        !           783:     switch (asi) {
        !           784:     case 0x80: // Primary
        !           785:     case 0x82: // Primary no-fault
        !           786:     case 0x88: // Primary LE
        !           787:     case 0x8a: // Primary no-fault LE
        !           788:         {
        !           789:             switch(size) {
        !           790:             case 1:
        !           791:                 ret = ldub_raw(T0);
        !           792:                 break;
        !           793:             case 2:
        !           794:                 ret = lduw_raw(T0 & ~1);
        !           795:                 break;
        !           796:             case 4:
        !           797:                 ret = ldl_raw(T0 & ~3);
        !           798:                 break;
        !           799:             default:
        !           800:             case 8:
        !           801:                 ret = ldq_raw(T0 & ~7);
        !           802:                 break;
        !           803:             }
        !           804:         }
        !           805:         break;
        !           806:     case 0x81: // Secondary
        !           807:     case 0x83: // Secondary no-fault
        !           808:     case 0x89: // Secondary LE
        !           809:     case 0x8b: // Secondary no-fault LE
        !           810:         // XXX
        !           811:         break;
        !           812:     default:
        !           813:         break;
        !           814:     }
        !           815: 
        !           816:     /* Convert from little endian */
        !           817:     switch (asi) {
        !           818:     case 0x88: // Primary LE
        !           819:     case 0x89: // Secondary LE
        !           820:     case 0x8a: // Primary no-fault LE
        !           821:     case 0x8b: // Secondary no-fault LE
        !           822:         switch(size) {
        !           823:         case 2:
        !           824:             ret = bswap16(ret);
        !           825:             break;
        !           826:         case 4:
        !           827:             ret = bswap32(ret);
        !           828:             break;
        !           829:         case 8:
        !           830:             ret = bswap64(ret);
        !           831:             break;
        !           832:         default:
        !           833:             break;
        !           834:         }
        !           835:     default:
        !           836:         break;
        !           837:     }
        !           838: 
        !           839:     /* Convert to signed number */
        !           840:     if (sign) {
        !           841:         switch(size) {
        !           842:         case 1:
        !           843:             ret = (int8_t) ret;
        !           844:             break;
        !           845:         case 2:
        !           846:             ret = (int16_t) ret;
        !           847:             break;
        !           848:         case 4:
        !           849:             ret = (int32_t) ret;
        !           850:             break;
        !           851:         default:
        !           852:             break;
        !           853:         }
        !           854:     }
        !           855:     T1 = ret;
        !           856: }
        !           857: 
        !           858: void helper_st_asi(int asi, int size)
        !           859: {
        !           860:     if (asi < 0x80)
        !           861:         raise_exception(TT_PRIV_ACT);
        !           862: 
        !           863:     /* Convert to little endian */
        !           864:     switch (asi) {
        !           865:     case 0x88: // Primary LE
        !           866:     case 0x89: // Secondary LE
        !           867:         switch(size) {
        !           868:         case 2:
        !           869:             T0 = bswap16(T0);
        !           870:             break;
        !           871:         case 4:
        !           872:             T0 = bswap32(T0);
        !           873:             break;
        !           874:         case 8:
        !           875:             T0 = bswap64(T0);
        !           876:             break;
        !           877:         default:
        !           878:             break;
        !           879:         }
        !           880:     default:
        !           881:         break;
        !           882:     }
        !           883: 
        !           884:     switch(asi) {
        !           885:     case 0x80: // Primary
        !           886:     case 0x88: // Primary LE
        !           887:         {
1.1.1.2   root      888:             switch(size) {
                    889:             case 1:
1.1.1.5 ! root      890:                 stb_raw(T0, T1);
1.1.1.2   root      891:                 break;
                    892:             case 2:
1.1.1.5 ! root      893:                 stw_raw(T0 & ~1, T1);
1.1.1.2   root      894:                 break;
                    895:             case 4:
1.1.1.5 ! root      896:                 stl_raw(T0 & ~3, T1);
1.1.1.2   root      897:                 break;
                    898:             case 8:
1.1.1.5 ! root      899:             default:
        !           900:                 stq_raw(T0 & ~7, T1);
1.1.1.2   root      901:                 break;
                    902:             }
1.1.1.5 ! root      903:         }
        !           904:         break;
        !           905:     case 0x81: // Secondary
        !           906:     case 0x89: // Secondary LE
        !           907:         // XXX
        !           908:         return;
        !           909: 
        !           910:     case 0x82: // Primary no-fault, RO
        !           911:     case 0x83: // Secondary no-fault, RO
        !           912:     case 0x8a: // Primary no-fault LE, RO
        !           913:     case 0x8b: // Secondary no-fault LE, RO
1.1       root      914:     default:
1.1.1.5 ! root      915:         do_unassigned_access(T0, 1, 0, 1);
        !           916:         return;
1.1       root      917:     }
                    918: }
                    919: 
1.1.1.5 ! root      920: #else /* CONFIG_USER_ONLY */
1.1       root      921: 
                    922: void helper_ld_asi(int asi, int size, int sign)
                    923: {
                    924:     uint64_t ret = 0;
                    925: 
1.1.1.5 ! root      926:     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
        !           927:         || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
        !           928:         raise_exception(TT_PRIV_ACT);
1.1       root      929: 
                    930:     switch (asi) {
1.1.1.5 ! root      931:     case 0x10: // As if user primary
        !           932:     case 0x18: // As if user primary LE
        !           933:     case 0x80: // Primary
        !           934:     case 0x82: // Primary no-fault
        !           935:     case 0x88: // Primary LE
        !           936:     case 0x8a: // Primary no-fault LE
        !           937:         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
        !           938:             if (env->hpstate & HS_PRIV) {
        !           939:                 switch(size) {
        !           940:                 case 1:
        !           941:                     ret = ldub_hypv(T0);
        !           942:                     break;
        !           943:                 case 2:
        !           944:                     ret = lduw_hypv(T0 & ~1);
        !           945:                     break;
        !           946:                 case 4:
        !           947:                     ret = ldl_hypv(T0 & ~3);
        !           948:                     break;
        !           949:                 default:
        !           950:                 case 8:
        !           951:                     ret = ldq_hypv(T0 & ~7);
        !           952:                     break;
        !           953:                 }
        !           954:             } else {
        !           955:                 switch(size) {
        !           956:                 case 1:
        !           957:                     ret = ldub_kernel(T0);
        !           958:                     break;
        !           959:                 case 2:
        !           960:                     ret = lduw_kernel(T0 & ~1);
        !           961:                     break;
        !           962:                 case 4:
        !           963:                     ret = ldl_kernel(T0 & ~3);
        !           964:                     break;
        !           965:                 default:
        !           966:                 case 8:
        !           967:                     ret = ldq_kernel(T0 & ~7);
        !           968:                     break;
        !           969:                 }
        !           970:             }
        !           971:         } else {
        !           972:             switch(size) {
        !           973:             case 1:
        !           974:                 ret = ldub_user(T0);
        !           975:                 break;
        !           976:             case 2:
        !           977:                 ret = lduw_user(T0 & ~1);
        !           978:                 break;
        !           979:             case 4:
        !           980:                 ret = ldl_user(T0 & ~3);
        !           981:                 break;
        !           982:             default:
        !           983:             case 8:
        !           984:                 ret = ldq_user(T0 & ~7);
        !           985:                 break;
        !           986:             }
        !           987:         }
        !           988:         break;
1.1       root      989:     case 0x14: // Bypass
                    990:     case 0x15: // Bypass, non-cacheable
1.1.1.5 ! root      991:     case 0x1c: // Bypass LE
        !           992:     case 0x1d: // Bypass, non-cacheable LE
        !           993:         {
1.1.1.2   root      994:             switch(size) {
                    995:             case 1:
                    996:                 ret = ldub_phys(T0);
                    997:                 break;
                    998:             case 2:
                    999:                 ret = lduw_phys(T0 & ~1);
                   1000:                 break;
                   1001:             case 4:
                   1002:                 ret = ldl_phys(T0 & ~3);
                   1003:                 break;
                   1004:             default:
                   1005:             case 8:
                   1006:                 ret = ldq_phys(T0 & ~7);
                   1007:                 break;
                   1008:             }
1.1.1.5 ! root     1009:             break;
        !          1010:         }
1.1       root     1011:     case 0x04: // Nucleus
                   1012:     case 0x0c: // Nucleus Little Endian (LE)
                   1013:     case 0x11: // As if user secondary
                   1014:     case 0x19: // As if user secondary LE
                   1015:     case 0x24: // Nucleus quad LDD 128 bit atomic
                   1016:     case 0x2c: // Nucleus quad LDD 128 bit atomic
                   1017:     case 0x4a: // UPA config
1.1.1.5 ! root     1018:     case 0x81: // Secondary
1.1       root     1019:     case 0x83: // Secondary no-fault
                   1020:     case 0x89: // Secondary LE
                   1021:     case 0x8b: // Secondary no-fault LE
1.1.1.5 ! root     1022:         // XXX
        !          1023:         break;
1.1       root     1024:     case 0x45: // LSU
1.1.1.5 ! root     1025:         ret = env->lsu;
        !          1026:         break;
1.1       root     1027:     case 0x50: // I-MMU regs
1.1.1.5 ! root     1028:         {
        !          1029:             int reg = (T0 >> 3) & 0xf;
1.1       root     1030: 
1.1.1.5 ! root     1031:             ret = env->immuregs[reg];
        !          1032:             break;
        !          1033:         }
1.1       root     1034:     case 0x51: // I-MMU 8k TSB pointer
                   1035:     case 0x52: // I-MMU 64k TSB pointer
                   1036:     case 0x55: // I-MMU data access
1.1.1.5 ! root     1037:         // XXX
        !          1038:         break;
1.1       root     1039:     case 0x56: // I-MMU tag read
1.1.1.5 ! root     1040:         {
        !          1041:             unsigned int i;
        !          1042: 
        !          1043:             for (i = 0; i < 64; i++) {
        !          1044:                 // Valid, ctx match, vaddr match
        !          1045:                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
        !          1046:                     env->itlb_tag[i] == T0) {
        !          1047:                     ret = env->itlb_tag[i];
        !          1048:                     break;
        !          1049:                 }
        !          1050:             }
        !          1051:             break;
        !          1052:         }
1.1       root     1053:     case 0x58: // D-MMU regs
1.1.1.5 ! root     1054:         {
        !          1055:             int reg = (T0 >> 3) & 0xf;
1.1       root     1056: 
1.1.1.5 ! root     1057:             ret = env->dmmuregs[reg];
        !          1058:             break;
        !          1059:         }
1.1       root     1060:     case 0x5e: // D-MMU tag read
1.1.1.5 ! root     1061:         {
        !          1062:             unsigned int i;
        !          1063: 
        !          1064:             for (i = 0; i < 64; i++) {
        !          1065:                 // Valid, ctx match, vaddr match
        !          1066:                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
        !          1067:                     env->dtlb_tag[i] == T0) {
        !          1068:                     ret = env->dtlb_tag[i];
        !          1069:                     break;
        !          1070:                 }
        !          1071:             }
        !          1072:             break;
        !          1073:         }
1.1       root     1074:     case 0x59: // D-MMU 8k TSB pointer
                   1075:     case 0x5a: // D-MMU 64k TSB pointer
                   1076:     case 0x5b: // D-MMU data pointer
                   1077:     case 0x5d: // D-MMU data access
                   1078:     case 0x48: // Interrupt dispatch, RO
                   1079:     case 0x49: // Interrupt data receive
                   1080:     case 0x7f: // Incoming interrupt vector, RO
1.1.1.5 ! root     1081:         // XXX
        !          1082:         break;
1.1       root     1083:     case 0x54: // I-MMU data in, WO
                   1084:     case 0x57: // I-MMU demap, WO
                   1085:     case 0x5c: // D-MMU data in, WO
                   1086:     case 0x5f: // D-MMU demap, WO
                   1087:     case 0x77: // Interrupt vector, WO
                   1088:     default:
1.1.1.5 ! root     1089:         do_unassigned_access(T0, 0, 0, 1);
        !          1090:         ret = 0;
        !          1091:         break;
        !          1092:     }
        !          1093: 
        !          1094:     /* Convert from little endian */
        !          1095:     switch (asi) {
        !          1096:     case 0x0c: // Nucleus Little Endian (LE)
        !          1097:     case 0x18: // As if user primary LE
        !          1098:     case 0x19: // As if user secondary LE
        !          1099:     case 0x1c: // Bypass LE
        !          1100:     case 0x1d: // Bypass, non-cacheable LE
        !          1101:     case 0x88: // Primary LE
        !          1102:     case 0x89: // Secondary LE
        !          1103:     case 0x8a: // Primary no-fault LE
        !          1104:     case 0x8b: // Secondary no-fault LE
        !          1105:         switch(size) {
        !          1106:         case 2:
        !          1107:             ret = bswap16(ret);
        !          1108:             break;
        !          1109:         case 4:
        !          1110:             ret = bswap32(ret);
        !          1111:             break;
        !          1112:         case 8:
        !          1113:             ret = bswap64(ret);
        !          1114:             break;
        !          1115:         default:
        !          1116:             break;
        !          1117:         }
        !          1118:     default:
        !          1119:         break;
        !          1120:     }
        !          1121: 
        !          1122:     /* Convert to signed number */
        !          1123:     if (sign) {
        !          1124:         switch(size) {
        !          1125:         case 1:
        !          1126:             ret = (int8_t) ret;
        !          1127:             break;
        !          1128:         case 2:
        !          1129:             ret = (int16_t) ret;
        !          1130:             break;
        !          1131:         case 4:
        !          1132:             ret = (int32_t) ret;
        !          1133:             break;
        !          1134:         default:
        !          1135:             break;
        !          1136:         }
1.1       root     1137:     }
                   1138:     T1 = ret;
                   1139: }
                   1140: 
1.1.1.5 ! root     1141: void helper_st_asi(int asi, int size)
1.1       root     1142: {
1.1.1.5 ! root     1143:     if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
        !          1144:         || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))
        !          1145:         raise_exception(TT_PRIV_ACT);
        !          1146: 
        !          1147:     /* Convert to little endian */
        !          1148:     switch (asi) {
        !          1149:     case 0x0c: // Nucleus Little Endian (LE)
        !          1150:     case 0x18: // As if user primary LE
        !          1151:     case 0x19: // As if user secondary LE
        !          1152:     case 0x1c: // Bypass LE
        !          1153:     case 0x1d: // Bypass, non-cacheable LE
        !          1154:     case 0x88: // Primary LE
        !          1155:     case 0x89: // Secondary LE
        !          1156:         switch(size) {
        !          1157:         case 2:
        !          1158:             T0 = bswap16(T0);
        !          1159:             break;
        !          1160:         case 4:
        !          1161:             T0 = bswap32(T0);
        !          1162:             break;
        !          1163:         case 8:
        !          1164:             T0 = bswap64(T0);
        !          1165:             break;
        !          1166:         default:
        !          1167:             break;
        !          1168:         }
        !          1169:     default:
        !          1170:         break;
        !          1171:     }
1.1       root     1172: 
                   1173:     switch(asi) {
1.1.1.5 ! root     1174:     case 0x10: // As if user primary
        !          1175:     case 0x18: // As if user primary LE
        !          1176:     case 0x80: // Primary
        !          1177:     case 0x88: // Primary LE
        !          1178:         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
        !          1179:             if (env->hpstate & HS_PRIV) {
        !          1180:                 switch(size) {
        !          1181:                 case 1:
        !          1182:                     stb_hypv(T0, T1);
        !          1183:                     break;
        !          1184:                 case 2:
        !          1185:                     stw_hypv(T0 & ~1, T1);
        !          1186:                     break;
        !          1187:                 case 4:
        !          1188:                     stl_hypv(T0 & ~3, T1);
        !          1189:                     break;
        !          1190:                 case 8:
        !          1191:                 default:
        !          1192:                     stq_hypv(T0 & ~7, T1);
        !          1193:                     break;
        !          1194:                 }
        !          1195:             } else {
        !          1196:                 switch(size) {
        !          1197:                 case 1:
        !          1198:                     stb_kernel(T0, T1);
        !          1199:                     break;
        !          1200:                 case 2:
        !          1201:                     stw_kernel(T0 & ~1, T1);
        !          1202:                     break;
        !          1203:                 case 4:
        !          1204:                     stl_kernel(T0 & ~3, T1);
        !          1205:                     break;
        !          1206:                 case 8:
        !          1207:                 default:
        !          1208:                     stq_kernel(T0 & ~7, T1);
        !          1209:                     break;
        !          1210:                 }
        !          1211:             }
        !          1212:         } else {
        !          1213:             switch(size) {
        !          1214:             case 1:
        !          1215:                 stb_user(T0, T1);
        !          1216:                 break;
        !          1217:             case 2:
        !          1218:                 stw_user(T0 & ~1, T1);
        !          1219:                 break;
        !          1220:             case 4:
        !          1221:                 stl_user(T0 & ~3, T1);
        !          1222:                 break;
        !          1223:             case 8:
        !          1224:             default:
        !          1225:                 stq_user(T0 & ~7, T1);
        !          1226:                 break;
        !          1227:             }
        !          1228:         }
        !          1229:         break;
1.1       root     1230:     case 0x14: // Bypass
                   1231:     case 0x15: // Bypass, non-cacheable
1.1.1.5 ! root     1232:     case 0x1c: // Bypass LE
        !          1233:     case 0x1d: // Bypass, non-cacheable LE
        !          1234:         {
1.1.1.2   root     1235:             switch(size) {
                   1236:             case 1:
                   1237:                 stb_phys(T0, T1);
                   1238:                 break;
                   1239:             case 2:
                   1240:                 stw_phys(T0 & ~1, T1);
                   1241:                 break;
                   1242:             case 4:
                   1243:                 stl_phys(T0 & ~3, T1);
                   1244:                 break;
                   1245:             case 8:
                   1246:             default:
                   1247:                 stq_phys(T0 & ~7, T1);
                   1248:                 break;
                   1249:             }
1.1.1.5 ! root     1250:         }
        !          1251:         return;
1.1       root     1252:     case 0x04: // Nucleus
                   1253:     case 0x0c: // Nucleus Little Endian (LE)
                   1254:     case 0x11: // As if user secondary
                   1255:     case 0x19: // As if user secondary LE
                   1256:     case 0x24: // Nucleus quad LDD 128 bit atomic
                   1257:     case 0x2c: // Nucleus quad LDD 128 bit atomic
                   1258:     case 0x4a: // UPA config
1.1.1.5 ! root     1259:     case 0x81: // Secondary
1.1       root     1260:     case 0x89: // Secondary LE
1.1.1.5 ! root     1261:         // XXX
        !          1262:         return;
1.1       root     1263:     case 0x45: // LSU
1.1.1.5 ! root     1264:         {
        !          1265:             uint64_t oldreg;
1.1       root     1266: 
1.1.1.5 ! root     1267:             oldreg = env->lsu;
        !          1268:             env->lsu = T1 & (DMMU_E | IMMU_E);
        !          1269:             // Mappings generated during D/I MMU disabled mode are
        !          1270:             // invalid in normal mode
        !          1271:             if (oldreg != env->lsu) {
        !          1272:                 DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);
1.1       root     1273: #ifdef DEBUG_MMU
1.1.1.5 ! root     1274:                 dump_mmu(env);
1.1       root     1275: #endif
1.1.1.5 ! root     1276:                 tlb_flush(env, 1);
        !          1277:             }
        !          1278:             return;
        !          1279:         }
1.1       root     1280:     case 0x50: // I-MMU regs
1.1.1.5 ! root     1281:         {
        !          1282:             int reg = (T0 >> 3) & 0xf;
        !          1283:             uint64_t oldreg;
        !          1284: 
        !          1285:             oldreg = env->immuregs[reg];
1.1       root     1286:             switch(reg) {
                   1287:             case 0: // RO
                   1288:             case 4:
                   1289:                 return;
                   1290:             case 1: // Not in I-MMU
                   1291:             case 2:
                   1292:             case 7:
                   1293:             case 8:
                   1294:                 return;
                   1295:             case 3: // SFSR
1.1.1.5 ! root     1296:                 if ((T1 & 1) == 0)
        !          1297:                     T1 = 0; // Clear SFSR
1.1       root     1298:                 break;
                   1299:             case 5: // TSB access
                   1300:             case 6: // Tag access
                   1301:             default:
                   1302:                 break;
                   1303:             }
1.1.1.5 ! root     1304:             env->immuregs[reg] = T1;
1.1       root     1305:             if (oldreg != env->immuregs[reg]) {
1.1.1.5 ! root     1306:                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
1.1       root     1307:             }
1.1.1.5 ! root     1308: #ifdef DEBUG_MMU
        !          1309:             dump_mmu(env);
1.1       root     1310: #endif
1.1.1.5 ! root     1311:             return;
        !          1312:         }
1.1       root     1313:     case 0x54: // I-MMU data in
1.1.1.5 ! root     1314:         {
        !          1315:             unsigned int i;
1.1       root     1316: 
1.1.1.5 ! root     1317:             // Try finding an invalid entry
        !          1318:             for (i = 0; i < 64; i++) {
        !          1319:                 if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
        !          1320:                     env->itlb_tag[i] = env->immuregs[6];
        !          1321:                     env->itlb_tte[i] = T1;
        !          1322:                     return;
        !          1323:                 }
        !          1324:             }
        !          1325:             // Try finding an unlocked entry
        !          1326:             for (i = 0; i < 64; i++) {
        !          1327:                 if ((env->itlb_tte[i] & 0x40) == 0) {
        !          1328:                     env->itlb_tag[i] = env->immuregs[6];
        !          1329:                     env->itlb_tte[i] = T1;
        !          1330:                     return;
        !          1331:                 }
        !          1332:             }
        !          1333:             // error state?
        !          1334:             return;
        !          1335:         }
1.1       root     1336:     case 0x55: // I-MMU data access
1.1.1.5 ! root     1337:         {
        !          1338:             unsigned int i = (T0 >> 3) & 0x3f;
1.1       root     1339: 
1.1.1.5 ! root     1340:             env->itlb_tag[i] = env->immuregs[6];
        !          1341:             env->itlb_tte[i] = T1;
        !          1342:             return;
        !          1343:         }
1.1       root     1344:     case 0x57: // I-MMU demap
1.1.1.5 ! root     1345:         // XXX
        !          1346:         return;
1.1       root     1347:     case 0x58: // D-MMU regs
1.1.1.5 ! root     1348:         {
        !          1349:             int reg = (T0 >> 3) & 0xf;
        !          1350:             uint64_t oldreg;
        !          1351: 
        !          1352:             oldreg = env->dmmuregs[reg];
1.1       root     1353:             switch(reg) {
                   1354:             case 0: // RO
                   1355:             case 4:
                   1356:                 return;
                   1357:             case 3: // SFSR
1.1.1.5 ! root     1358:                 if ((T1 & 1) == 0) {
        !          1359:                     T1 = 0; // Clear SFSR, Fault address
        !          1360:                     env->dmmuregs[4] = 0;
        !          1361:                 }
        !          1362:                 env->dmmuregs[reg] = T1;
1.1       root     1363:                 break;
                   1364:             case 1: // Primary context
                   1365:             case 2: // Secondary context
                   1366:             case 5: // TSB access
                   1367:             case 6: // Tag access
                   1368:             case 7: // Virtual Watchpoint
                   1369:             case 8: // Physical Watchpoint
                   1370:             default:
                   1371:                 break;
                   1372:             }
1.1.1.5 ! root     1373:             env->dmmuregs[reg] = T1;
1.1       root     1374:             if (oldreg != env->dmmuregs[reg]) {
1.1.1.5 ! root     1375:                 DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
1.1       root     1376:             }
1.1.1.5 ! root     1377: #ifdef DEBUG_MMU
        !          1378:             dump_mmu(env);
1.1       root     1379: #endif
1.1.1.5 ! root     1380:             return;
        !          1381:         }
1.1       root     1382:     case 0x5c: // D-MMU data in
1.1.1.5 ! root     1383:         {
        !          1384:             unsigned int i;
1.1       root     1385: 
1.1.1.5 ! root     1386:             // Try finding an invalid entry
        !          1387:             for (i = 0; i < 64; i++) {
        !          1388:                 if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
        !          1389:                     env->dtlb_tag[i] = env->dmmuregs[6];
        !          1390:                     env->dtlb_tte[i] = T1;
        !          1391:                     return;
        !          1392:                 }
        !          1393:             }
        !          1394:             // Try finding an unlocked entry
        !          1395:             for (i = 0; i < 64; i++) {
        !          1396:                 if ((env->dtlb_tte[i] & 0x40) == 0) {
        !          1397:                     env->dtlb_tag[i] = env->dmmuregs[6];
        !          1398:                     env->dtlb_tte[i] = T1;
        !          1399:                     return;
        !          1400:                 }
        !          1401:             }
        !          1402:             // error state?
        !          1403:             return;
        !          1404:         }
1.1       root     1405:     case 0x5d: // D-MMU data access
1.1.1.5 ! root     1406:         {
        !          1407:             unsigned int i = (T0 >> 3) & 0x3f;
1.1       root     1408: 
1.1.1.5 ! root     1409:             env->dtlb_tag[i] = env->dmmuregs[6];
        !          1410:             env->dtlb_tte[i] = T1;
        !          1411:             return;
        !          1412:         }
1.1       root     1413:     case 0x5f: // D-MMU demap
                   1414:     case 0x49: // Interrupt data receive
1.1.1.5 ! root     1415:         // XXX
        !          1416:         return;
1.1       root     1417:     case 0x51: // I-MMU 8k TSB pointer, RO
                   1418:     case 0x52: // I-MMU 64k TSB pointer, RO
                   1419:     case 0x56: // I-MMU tag read, RO
                   1420:     case 0x59: // D-MMU 8k TSB pointer, RO
                   1421:     case 0x5a: // D-MMU 64k TSB pointer, RO
                   1422:     case 0x5b: // D-MMU data pointer, RO
                   1423:     case 0x5e: // D-MMU tag read, RO
                   1424:     case 0x48: // Interrupt dispatch, RO
                   1425:     case 0x7f: // Incoming interrupt vector, RO
                   1426:     case 0x82: // Primary no-fault, RO
                   1427:     case 0x83: // Secondary no-fault, RO
                   1428:     case 0x8a: // Primary no-fault LE, RO
                   1429:     case 0x8b: // Secondary no-fault LE, RO
                   1430:     default:
1.1.1.5 ! root     1431:         do_unassigned_access(T0, 1, 0, 1);
        !          1432:         return;
        !          1433:     }
        !          1434: }
        !          1435: #endif /* CONFIG_USER_ONLY */
        !          1436: 
        !          1437: void helper_ldf_asi(int asi, int size, int rd)
        !          1438: {
        !          1439:     target_ulong tmp_T0 = T0, tmp_T1 = T1;
        !          1440:     unsigned int i;
        !          1441: 
        !          1442:     switch (asi) {
        !          1443:     case 0xf0: // Block load primary
        !          1444:     case 0xf1: // Block load secondary
        !          1445:     case 0xf8: // Block load primary LE
        !          1446:     case 0xf9: // Block load secondary LE
        !          1447:         if (rd & 7) {
        !          1448:             raise_exception(TT_ILL_INSN);
        !          1449:             return;
        !          1450:         }
        !          1451:         if (T0 & 0x3f) {
        !          1452:             raise_exception(TT_UNALIGNED);
        !          1453:             return;
        !          1454:         }
        !          1455:         for (i = 0; i < 16; i++) {
        !          1456:             helper_ld_asi(asi & 0x8f, 4, 0);
        !          1457:             *(uint32_t *)&env->fpr[rd++] = T1;
        !          1458:             T0 += 4;
        !          1459:         }
        !          1460:         T0 = tmp_T0;
        !          1461:         T1 = tmp_T1;
        !          1462: 
        !          1463:         return;
        !          1464:     default:
        !          1465:         break;
        !          1466:     }
        !          1467: 
        !          1468:     helper_ld_asi(asi, size, 0);
        !          1469:     switch(size) {
        !          1470:     default:
        !          1471:     case 4:
        !          1472:         *((uint32_t *)&FT0) = T1;
        !          1473:         break;
        !          1474:     case 8:
        !          1475:         *((int64_t *)&DT0) = T1;
        !          1476:         break;
        !          1477: #if defined(CONFIG_USER_ONLY)
        !          1478:     case 16:
        !          1479:         // XXX
        !          1480:         break;
        !          1481: #endif
1.1       root     1482:     }
1.1.1.5 ! root     1483:     T1 = tmp_T1;
1.1       root     1484: }
1.1.1.5 ! root     1485: 
        !          1486: void helper_stf_asi(int asi, int size, int rd)
        !          1487: {
        !          1488:     target_ulong tmp_T0 = T0, tmp_T1 = T1;
        !          1489:     unsigned int i;
        !          1490: 
        !          1491:     switch (asi) {
        !          1492:     case 0xf0: // Block store primary
        !          1493:     case 0xf1: // Block store secondary
        !          1494:     case 0xf8: // Block store primary LE
        !          1495:     case 0xf9: // Block store secondary LE
        !          1496:         if (rd & 7) {
        !          1497:             raise_exception(TT_ILL_INSN);
        !          1498:             return;
        !          1499:         }
        !          1500:         if (T0 & 0x3f) {
        !          1501:             raise_exception(TT_UNALIGNED);
        !          1502:             return;
        !          1503:         }
        !          1504:         for (i = 0; i < 16; i++) {
        !          1505:             T1 = *(uint32_t *)&env->fpr[rd++];
        !          1506:             helper_st_asi(asi & 0x8f, 4);
        !          1507:             T0 += 4;
        !          1508:         }
        !          1509:         T0 = tmp_T0;
        !          1510:         T1 = tmp_T1;
        !          1511: 
        !          1512:         return;
        !          1513:     default:
        !          1514:         break;
        !          1515:     }
        !          1516: 
        !          1517:     switch(size) {
        !          1518:     default:
        !          1519:     case 4:
        !          1520:         T1 = *((uint32_t *)&FT0);
        !          1521:         break;
        !          1522:     case 8:
        !          1523:         T1 = *((int64_t *)&DT0);
        !          1524:         break;
        !          1525: #if defined(CONFIG_USER_ONLY)
        !          1526:     case 16:
        !          1527:         // XXX
        !          1528:         break;
1.1       root     1529: #endif
1.1.1.5 ! root     1530:     }
        !          1531:     helper_st_asi(asi, size);
        !          1532:     T1 = tmp_T1;
        !          1533: }
        !          1534: 
        !          1535: #endif /* TARGET_SPARC64 */
1.1       root     1536: 
                   1537: #ifndef TARGET_SPARC64
                   1538: void helper_rett()
                   1539: {
                   1540:     unsigned int cwp;
                   1541: 
1.1.1.5 ! root     1542:     if (env->psret == 1)
        !          1543:         raise_exception(TT_ILL_INSN);
        !          1544: 
1.1       root     1545:     env->psret = 1;
1.1.1.5 ! root     1546:     cwp = (env->cwp + 1) & (NWINDOWS - 1);
1.1       root     1547:     if (env->wim & (1 << cwp)) {
                   1548:         raise_exception(TT_WIN_UNF);
                   1549:     }
                   1550:     set_cwp(cwp);
                   1551:     env->psrs = env->psrps;
                   1552: }
                   1553: #endif
                   1554: 
                   1555: void helper_ldfsr(void)
                   1556: {
                   1557:     int rnd_mode;
                   1558:     switch (env->fsr & FSR_RD_MASK) {
                   1559:     case FSR_RD_NEAREST:
                   1560:         rnd_mode = float_round_nearest_even;
1.1.1.5 ! root     1561:         break;
1.1       root     1562:     default:
                   1563:     case FSR_RD_ZERO:
                   1564:         rnd_mode = float_round_to_zero;
1.1.1.5 ! root     1565:         break;
1.1       root     1566:     case FSR_RD_POS:
                   1567:         rnd_mode = float_round_up;
1.1.1.5 ! root     1568:         break;
1.1       root     1569:     case FSR_RD_NEG:
                   1570:         rnd_mode = float_round_down;
1.1.1.5 ! root     1571:         break;
1.1       root     1572:     }
                   1573:     set_float_rounding_mode(rnd_mode, &env->fp_status);
                   1574: }
                   1575: 
                   1576: void helper_debug()
                   1577: {
                   1578:     env->exception_index = EXCP_DEBUG;
                   1579:     cpu_loop_exit();
                   1580: }
                   1581: 
                   1582: #ifndef TARGET_SPARC64
                   1583: void do_wrpsr()
                   1584: {
1.1.1.5 ! root     1585:     if ((T0 & PSR_CWP) >= NWINDOWS)
        !          1586:         raise_exception(TT_ILL_INSN);
        !          1587:     else
        !          1588:         PUT_PSR(env, T0);
1.1       root     1589: }
                   1590: 
                   1591: void do_rdpsr()
                   1592: {
                   1593:     T0 = GET_PSR(env);
                   1594: }
                   1595: 
                   1596: #else
                   1597: 
                   1598: void do_popc()
                   1599: {
1.1.1.5 ! root     1600:     T0 = ctpop64(T1);
1.1       root     1601: }
                   1602: 
                   1603: static inline uint64_t *get_gregset(uint64_t pstate)
                   1604: {
                   1605:     switch (pstate) {
                   1606:     default:
                   1607:     case 0:
1.1.1.5 ! root     1608:         return env->bgregs;
1.1       root     1609:     case PS_AG:
1.1.1.5 ! root     1610:         return env->agregs;
1.1       root     1611:     case PS_MG:
1.1.1.5 ! root     1612:         return env->mgregs;
1.1       root     1613:     case PS_IG:
1.1.1.5 ! root     1614:         return env->igregs;
1.1       root     1615:     }
                   1616: }
                   1617: 
1.1.1.5 ! root     1618: static inline void change_pstate(uint64_t new_pstate)
1.1       root     1619: {
1.1.1.5 ! root     1620:     uint64_t pstate_regs, new_pstate_regs;
1.1       root     1621:     uint64_t *src, *dst;
                   1622: 
                   1623:     pstate_regs = env->pstate & 0xc01;
                   1624:     new_pstate_regs = new_pstate & 0xc01;
                   1625:     if (new_pstate_regs != pstate_regs) {
1.1.1.5 ! root     1626:         // Switch global register bank
        !          1627:         src = get_gregset(new_pstate_regs);
        !          1628:         dst = get_gregset(pstate_regs);
        !          1629:         memcpy32(dst, env->gregs);
        !          1630:         memcpy32(env->gregs, src);
1.1       root     1631:     }
                   1632:     env->pstate = new_pstate;
                   1633: }
                   1634: 
1.1.1.5 ! root     1635: void do_wrpstate(void)
        !          1636: {
        !          1637:     change_pstate(T0 & 0xf3f);
        !          1638: }
        !          1639: 
1.1       root     1640: void do_done(void)
                   1641: {
                   1642:     env->tl--;
                   1643:     env->pc = env->tnpc[env->tl];
                   1644:     env->npc = env->tnpc[env->tl] + 4;
                   1645:     PUT_CCR(env, env->tstate[env->tl] >> 32);
                   1646:     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1.1.1.5 ! root     1647:     change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
        !          1648:     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1.1       root     1649: }
                   1650: 
                   1651: void do_retry(void)
                   1652: {
                   1653:     env->tl--;
                   1654:     env->pc = env->tpc[env->tl];
                   1655:     env->npc = env->tnpc[env->tl];
                   1656:     PUT_CCR(env, env->tstate[env->tl] >> 32);
                   1657:     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
1.1.1.5 ! root     1658:     change_pstate((env->tstate[env->tl] >> 8) & 0xf3f);
        !          1659:     PUT_CWP64(env, env->tstate[env->tl] & 0xff);
1.1       root     1660: }
                   1661: #endif
                   1662: 
                   1663: void set_cwp(int new_cwp)
                   1664: {
                   1665:     /* put the modified wrap registers at their proper location */
                   1666:     if (env->cwp == (NWINDOWS - 1))
                   1667:         memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
                   1668:     env->cwp = new_cwp;
                   1669:     /* put the wrap registers at their temporary location */
                   1670:     if (new_cwp == (NWINDOWS - 1))
                   1671:         memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
                   1672:     env->regwptr = env->regbase + (new_cwp * 16);
                   1673:     REGWPTR = env->regwptr;
                   1674: }
                   1675: 
                   1676: void cpu_set_cwp(CPUState *env1, int new_cwp)
                   1677: {
                   1678:     CPUState *saved_env;
                   1679: #ifdef reg_REGWPTR
                   1680:     target_ulong *saved_regwptr;
                   1681: #endif
                   1682: 
                   1683:     saved_env = env;
                   1684: #ifdef reg_REGWPTR
                   1685:     saved_regwptr = REGWPTR;
                   1686: #endif
                   1687:     env = env1;
                   1688:     set_cwp(new_cwp);
                   1689:     env = saved_env;
                   1690: #ifdef reg_REGWPTR
                   1691:     REGWPTR = saved_regwptr;
                   1692: #endif
                   1693: }
                   1694: 
                   1695: #ifdef TARGET_SPARC64
1.1.1.5 ! root     1696: #ifdef DEBUG_PCALL
        !          1697: static const char * const excp_names[0x50] = {
        !          1698:     [TT_TFAULT] = "Instruction Access Fault",
        !          1699:     [TT_TMISS] = "Instruction Access MMU Miss",
        !          1700:     [TT_CODE_ACCESS] = "Instruction Access Error",
        !          1701:     [TT_ILL_INSN] = "Illegal Instruction",
        !          1702:     [TT_PRIV_INSN] = "Privileged Instruction",
        !          1703:     [TT_NFPU_INSN] = "FPU Disabled",
        !          1704:     [TT_FP_EXCP] = "FPU Exception",
        !          1705:     [TT_TOVF] = "Tag Overflow",
        !          1706:     [TT_CLRWIN] = "Clean Windows",
        !          1707:     [TT_DIV_ZERO] = "Division By Zero",
        !          1708:     [TT_DFAULT] = "Data Access Fault",
        !          1709:     [TT_DMISS] = "Data Access MMU Miss",
        !          1710:     [TT_DATA_ACCESS] = "Data Access Error",
        !          1711:     [TT_DPROT] = "Data Protection Error",
        !          1712:     [TT_UNALIGNED] = "Unaligned Memory Access",
        !          1713:     [TT_PRIV_ACT] = "Privileged Action",
        !          1714:     [TT_EXTINT | 0x1] = "External Interrupt 1",
        !          1715:     [TT_EXTINT | 0x2] = "External Interrupt 2",
        !          1716:     [TT_EXTINT | 0x3] = "External Interrupt 3",
        !          1717:     [TT_EXTINT | 0x4] = "External Interrupt 4",
        !          1718:     [TT_EXTINT | 0x5] = "External Interrupt 5",
        !          1719:     [TT_EXTINT | 0x6] = "External Interrupt 6",
        !          1720:     [TT_EXTINT | 0x7] = "External Interrupt 7",
        !          1721:     [TT_EXTINT | 0x8] = "External Interrupt 8",
        !          1722:     [TT_EXTINT | 0x9] = "External Interrupt 9",
        !          1723:     [TT_EXTINT | 0xa] = "External Interrupt 10",
        !          1724:     [TT_EXTINT | 0xb] = "External Interrupt 11",
        !          1725:     [TT_EXTINT | 0xc] = "External Interrupt 12",
        !          1726:     [TT_EXTINT | 0xd] = "External Interrupt 13",
        !          1727:     [TT_EXTINT | 0xe] = "External Interrupt 14",
        !          1728:     [TT_EXTINT | 0xf] = "External Interrupt 15",
        !          1729: };
        !          1730: #endif
        !          1731: 
1.1       root     1732: void do_interrupt(int intno)
                   1733: {
                   1734: #ifdef DEBUG_PCALL
                   1735:     if (loglevel & CPU_LOG_INT) {
1.1.1.5 ! root     1736:         static int count;
        !          1737:         const char *name;
        !          1738: 
        !          1739:         if (intno < 0 || intno >= 0x180 || (intno > 0x4f && intno < 0x80))
        !          1740:             name = "Unknown";
        !          1741:         else if (intno >= 0x100)
        !          1742:             name = "Trap Instruction";
        !          1743:         else if (intno >= 0xc0)
        !          1744:             name = "Window Fill";
        !          1745:         else if (intno >= 0x80)
        !          1746:             name = "Window Spill";
        !          1747:         else {
        !          1748:             name = excp_names[intno];
        !          1749:             if (!name)
        !          1750:                 name = "Unknown";
        !          1751:         }
        !          1752: 
        !          1753:         fprintf(logfile, "%6d: %s (v=%04x) pc=%016" PRIx64 " npc=%016" PRIx64
        !          1754:                 " SP=%016" PRIx64 "\n",
        !          1755:                 count, name, intno,
1.1       root     1756:                 env->pc,
                   1757:                 env->npc, env->regwptr[6]);
1.1.1.5 ! root     1758:         cpu_dump_state(env, logfile, fprintf, 0);
1.1       root     1759: #if 0
1.1.1.5 ! root     1760:         {
        !          1761:             int i;
        !          1762:             uint8_t *ptr;
        !          1763: 
        !          1764:             fprintf(logfile, "       code=");
        !          1765:             ptr = (uint8_t *)env->pc;
        !          1766:             for(i = 0; i < 16; i++) {
        !          1767:                 fprintf(logfile, " %02x", ldub(ptr + i));
        !          1768:             }
        !          1769:             fprintf(logfile, "\n");
        !          1770:         }
1.1       root     1771: #endif
1.1.1.5 ! root     1772:         count++;
1.1       root     1773:     }
                   1774: #endif
1.1.1.5 ! root     1775: #if !defined(CONFIG_USER_ONLY)
1.1       root     1776:     if (env->tl == MAXTL) {
1.1.1.2   root     1777:         cpu_abort(env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
1.1.1.5 ! root     1778:         return;
1.1       root     1779:     }
                   1780: #endif
                   1781:     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
1.1.1.5 ! root     1782:         ((env->pstate & 0xf3f) << 8) | GET_CWP64(env);
1.1       root     1783:     env->tpc[env->tl] = env->pc;
                   1784:     env->tnpc[env->tl] = env->npc;
                   1785:     env->tt[env->tl] = intno;
1.1.1.5 ! root     1786:     change_pstate(PS_PEF | PS_PRIV | PS_AG);
        !          1787: 
        !          1788:     if (intno == TT_CLRWIN)
        !          1789:         set_cwp((env->cwp - 1) & (NWINDOWS - 1));
        !          1790:     else if ((intno & 0x1c0) == TT_SPILL)
        !          1791:         set_cwp((env->cwp - env->cansave - 2) & (NWINDOWS - 1));
        !          1792:     else if ((intno & 0x1c0) == TT_FILL)
        !          1793:         set_cwp((env->cwp + 1) & (NWINDOWS - 1));
1.1       root     1794:     env->tbr &= ~0x7fffULL;
                   1795:     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
                   1796:     if (env->tl < MAXTL - 1) {
1.1.1.5 ! root     1797:         env->tl++;
1.1       root     1798:     } else {
1.1.1.5 ! root     1799:         env->pstate |= PS_RED;
        !          1800:         if (env->tl != MAXTL)
        !          1801:             env->tl++;
1.1       root     1802:     }
                   1803:     env->pc = env->tbr;
                   1804:     env->npc = env->pc + 4;
                   1805:     env->exception_index = 0;
                   1806: }
                   1807: #else
1.1.1.5 ! root     1808: #ifdef DEBUG_PCALL
        !          1809: static const char * const excp_names[0x80] = {
        !          1810:     [TT_TFAULT] = "Instruction Access Fault",
        !          1811:     [TT_ILL_INSN] = "Illegal Instruction",
        !          1812:     [TT_PRIV_INSN] = "Privileged Instruction",
        !          1813:     [TT_NFPU_INSN] = "FPU Disabled",
        !          1814:     [TT_WIN_OVF] = "Window Overflow",
        !          1815:     [TT_WIN_UNF] = "Window Underflow",
        !          1816:     [TT_UNALIGNED] = "Unaligned Memory Access",
        !          1817:     [TT_FP_EXCP] = "FPU Exception",
        !          1818:     [TT_DFAULT] = "Data Access Fault",
        !          1819:     [TT_TOVF] = "Tag Overflow",
        !          1820:     [TT_EXTINT | 0x1] = "External Interrupt 1",
        !          1821:     [TT_EXTINT | 0x2] = "External Interrupt 2",
        !          1822:     [TT_EXTINT | 0x3] = "External Interrupt 3",
        !          1823:     [TT_EXTINT | 0x4] = "External Interrupt 4",
        !          1824:     [TT_EXTINT | 0x5] = "External Interrupt 5",
        !          1825:     [TT_EXTINT | 0x6] = "External Interrupt 6",
        !          1826:     [TT_EXTINT | 0x7] = "External Interrupt 7",
        !          1827:     [TT_EXTINT | 0x8] = "External Interrupt 8",
        !          1828:     [TT_EXTINT | 0x9] = "External Interrupt 9",
        !          1829:     [TT_EXTINT | 0xa] = "External Interrupt 10",
        !          1830:     [TT_EXTINT | 0xb] = "External Interrupt 11",
        !          1831:     [TT_EXTINT | 0xc] = "External Interrupt 12",
        !          1832:     [TT_EXTINT | 0xd] = "External Interrupt 13",
        !          1833:     [TT_EXTINT | 0xe] = "External Interrupt 14",
        !          1834:     [TT_EXTINT | 0xf] = "External Interrupt 15",
        !          1835:     [TT_TOVF] = "Tag Overflow",
        !          1836:     [TT_CODE_ACCESS] = "Instruction Access Error",
        !          1837:     [TT_DATA_ACCESS] = "Data Access Error",
        !          1838:     [TT_DIV_ZERO] = "Division By Zero",
        !          1839:     [TT_NCP_INSN] = "Coprocessor Disabled",
        !          1840: };
        !          1841: #endif
        !          1842: 
1.1       root     1843: void do_interrupt(int intno)
                   1844: {
                   1845:     int cwp;
                   1846: 
                   1847: #ifdef DEBUG_PCALL
                   1848:     if (loglevel & CPU_LOG_INT) {
1.1.1.5 ! root     1849:         static int count;
        !          1850:         const char *name;
        !          1851: 
        !          1852:         if (intno < 0 || intno >= 0x100)
        !          1853:             name = "Unknown";
        !          1854:         else if (intno >= 0x80)
        !          1855:             name = "Trap Instruction";
        !          1856:         else {
        !          1857:             name = excp_names[intno];
        !          1858:             if (!name)
        !          1859:                 name = "Unknown";
        !          1860:         }
        !          1861: 
        !          1862:         fprintf(logfile, "%6d: %s (v=%02x) pc=%08x npc=%08x SP=%08x\n",
        !          1863:                 count, name, intno,
1.1       root     1864:                 env->pc,
                   1865:                 env->npc, env->regwptr[6]);
1.1.1.5 ! root     1866:         cpu_dump_state(env, logfile, fprintf, 0);
1.1       root     1867: #if 0
1.1.1.5 ! root     1868:         {
        !          1869:             int i;
        !          1870:             uint8_t *ptr;
        !          1871: 
        !          1872:             fprintf(logfile, "       code=");
        !          1873:             ptr = (uint8_t *)env->pc;
        !          1874:             for(i = 0; i < 16; i++) {
        !          1875:                 fprintf(logfile, " %02x", ldub(ptr + i));
        !          1876:             }
        !          1877:             fprintf(logfile, "\n");
        !          1878:         }
1.1       root     1879: #endif
1.1.1.5 ! root     1880:         count++;
1.1       root     1881:     }
                   1882: #endif
1.1.1.5 ! root     1883: #if !defined(CONFIG_USER_ONLY)
1.1       root     1884:     if (env->psret == 0) {
1.1.1.2   root     1885:         cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
1.1.1.5 ! root     1886:         return;
1.1       root     1887:     }
                   1888: #endif
                   1889:     env->psret = 0;
1.1.1.5 ! root     1890:     cwp = (env->cwp - 1) & (NWINDOWS - 1);
1.1       root     1891:     set_cwp(cwp);
                   1892:     env->regwptr[9] = env->pc;
                   1893:     env->regwptr[10] = env->npc;
                   1894:     env->psrps = env->psrs;
                   1895:     env->psrs = 1;
                   1896:     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
                   1897:     env->pc = env->tbr;
                   1898:     env->npc = env->pc + 4;
                   1899:     env->exception_index = 0;
                   1900: }
                   1901: #endif
                   1902: 
1.1.1.5 ! root     1903: #if !defined(CONFIG_USER_ONLY)
        !          1904: 
        !          1905: static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
        !          1906:                                 void *retaddr);
1.1       root     1907: 
                   1908: #define MMUSUFFIX _mmu
1.1.1.5 ! root     1909: #define ALIGNED_ONLY
        !          1910: #ifdef __s390__
        !          1911: # define GETPC() ((void*)((unsigned long)__builtin_return_address(0) & 0x7fffffffUL))
        !          1912: #else
        !          1913: # define GETPC() (__builtin_return_address(0))
        !          1914: #endif
1.1       root     1915: 
                   1916: #define SHIFT 0
                   1917: #include "softmmu_template.h"
                   1918: 
                   1919: #define SHIFT 1
                   1920: #include "softmmu_template.h"
                   1921: 
                   1922: #define SHIFT 2
                   1923: #include "softmmu_template.h"
                   1924: 
                   1925: #define SHIFT 3
                   1926: #include "softmmu_template.h"
                   1927: 
1.1.1.5 ! root     1928: static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
        !          1929:                                 void *retaddr)
        !          1930: {
        !          1931: #ifdef DEBUG_UNALIGNED
        !          1932:     printf("Unaligned access to 0x%x from 0x%x\n", addr, env->pc);
        !          1933: #endif
        !          1934:     raise_exception(TT_UNALIGNED);
        !          1935: }
1.1       root     1936: 
                   1937: /* try to fill the TLB and return an exception if error. If retaddr is
                   1938:    NULL, it means that the function was called in C code (i.e. not
                   1939:    from generated code or from helper.c) */
                   1940: /* XXX: fix it to restore all registers */
1.1.1.5 ! root     1941: void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
1.1       root     1942: {
                   1943:     TranslationBlock *tb;
                   1944:     int ret;
                   1945:     unsigned long pc;
                   1946:     CPUState *saved_env;
                   1947: 
                   1948:     /* XXX: hack to restore env in all cases, even if not called from
                   1949:        generated code */
                   1950:     saved_env = env;
                   1951:     env = cpu_single_env;
                   1952: 
1.1.1.5 ! root     1953:     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
1.1       root     1954:     if (ret) {
                   1955:         if (retaddr) {
                   1956:             /* now we have a real cpu fault */
                   1957:             pc = (unsigned long)retaddr;
                   1958:             tb = tb_find_pc(pc);
                   1959:             if (tb) {
                   1960:                 /* the PC is inside the translated code. It means that we have
                   1961:                    a virtual CPU fault */
                   1962:                 cpu_restore_state(tb, env, pc, (void *)T2);
                   1963:             }
                   1964:         }
                   1965:         cpu_loop_exit();
                   1966:     }
                   1967:     env = saved_env;
                   1968: }
                   1969: 
                   1970: #endif
1.1.1.5 ! root     1971: 
        !          1972: #ifndef TARGET_SPARC64
        !          1973: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
        !          1974:                           int is_asi)
        !          1975: {
        !          1976:     CPUState *saved_env;
        !          1977: 
        !          1978:     /* XXX: hack to restore env in all cases, even if not called from
        !          1979:        generated code */
        !          1980:     saved_env = env;
        !          1981:     env = cpu_single_env;
        !          1982: #ifdef DEBUG_UNASSIGNED
        !          1983:     if (is_asi)
        !          1984:         printf("Unassigned mem %s access to " TARGET_FMT_plx " asi 0x%02x from "
        !          1985:                TARGET_FMT_lx "\n",
        !          1986:                is_exec ? "exec" : is_write ? "write" : "read", addr, is_asi,
        !          1987:                env->pc);
        !          1988:     else
        !          1989:         printf("Unassigned mem %s access to " TARGET_FMT_plx " from "
        !          1990:                TARGET_FMT_lx "\n",
        !          1991:                is_exec ? "exec" : is_write ? "write" : "read", addr, env->pc);
        !          1992: #endif
        !          1993:     if (env->mmuregs[3]) /* Fault status register */
        !          1994:         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
        !          1995:     if (is_asi)
        !          1996:         env->mmuregs[3] |= 1 << 16;
        !          1997:     if (env->psrs)
        !          1998:         env->mmuregs[3] |= 1 << 5;
        !          1999:     if (is_exec)
        !          2000:         env->mmuregs[3] |= 1 << 6;
        !          2001:     if (is_write)
        !          2002:         env->mmuregs[3] |= 1 << 7;
        !          2003:     env->mmuregs[3] |= (5 << 2) | 2;
        !          2004:     env->mmuregs[4] = addr; /* Fault address register */
        !          2005:     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
        !          2006:         if (is_exec)
        !          2007:             raise_exception(TT_CODE_ACCESS);
        !          2008:         else
        !          2009:             raise_exception(TT_DATA_ACCESS);
        !          2010:     }
        !          2011:     env = saved_env;
        !          2012: }
        !          2013: #else
        !          2014: void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
        !          2015:                           int is_asi)
        !          2016: {
        !          2017: #ifdef DEBUG_UNASSIGNED
        !          2018:     CPUState *saved_env;
        !          2019: 
        !          2020:     /* XXX: hack to restore env in all cases, even if not called from
        !          2021:        generated code */
        !          2022:     saved_env = env;
        !          2023:     env = cpu_single_env;
        !          2024:     printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n",
        !          2025:            addr, env->pc);
        !          2026:     env = saved_env;
        !          2027: #endif
        !          2028:     if (is_exec)
        !          2029:         raise_exception(TT_CODE_ACCESS);
        !          2030:     else
        !          2031:         raise_exception(TT_DATA_ACCESS);
        !          2032: }
        !          2033: #endif
        !          2034: 

unix.superglobalmegacorp.com

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