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

1.1     ! root        1: #include "exec.h"
        !             2: 
        !             3: //#define DEBUG_PCALL
        !             4: //#define DEBUG_MMU
        !             5: 
        !             6: void raise_exception(int tt)
        !             7: {
        !             8:     env->exception_index = tt;
        !             9:     cpu_loop_exit();
        !            10: }   
        !            11: 
        !            12: #ifdef USE_INT_TO_FLOAT_HELPERS
        !            13: void do_fitos(void)
        !            14: {
        !            15:     FT0 = (float) *((int32_t *)&FT1);
        !            16: }
        !            17: 
        !            18: void do_fitod(void)
        !            19: {
        !            20:     DT0 = (double) *((int32_t *)&FT1);
        !            21: }
        !            22: #endif
        !            23: 
        !            24: void do_fabss(void)
        !            25: {
        !            26:     FT0 = float32_abs(FT1);
        !            27: }
        !            28: 
        !            29: #ifdef TARGET_SPARC64
        !            30: void do_fabsd(void)
        !            31: {
        !            32:     DT0 = float64_abs(DT1);
        !            33: }
        !            34: #endif
        !            35: 
        !            36: void do_fsqrts(void)
        !            37: {
        !            38:     FT0 = float32_sqrt(FT1, &env->fp_status);
        !            39: }
        !            40: 
        !            41: void do_fsqrtd(void)
        !            42: {
        !            43:     DT0 = float64_sqrt(DT1, &env->fp_status);
        !            44: }
        !            45: 
        !            46: #define FS 0
        !            47: void do_fcmps (void)
        !            48: {
        !            49:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !            50:     if (isnan(FT0) || isnan(FT1)) {
        !            51:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !            52:        if (env->fsr & FSR_NVM) {
        !            53:            env->fsr |= T0;
        !            54:            raise_exception(TT_FP_EXCP);
        !            55:        } else {
        !            56:            env->fsr |= FSR_NVA;
        !            57:        }
        !            58:     } else if (FT0 < FT1) {
        !            59:         T0 = FSR_FCC0 << FS;
        !            60:     } else if (FT0 > FT1) {
        !            61:         T0 = FSR_FCC1 << FS;
        !            62:     } else {
        !            63:         T0 = 0;
        !            64:     }
        !            65:     env->fsr |= T0;
        !            66: }
        !            67: 
        !            68: void do_fcmpd (void)
        !            69: {
        !            70:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !            71:     if (isnan(DT0) || isnan(DT1)) {
        !            72:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !            73:        if (env->fsr & FSR_NVM) {
        !            74:            env->fsr |= T0;
        !            75:            raise_exception(TT_FP_EXCP);
        !            76:        } else {
        !            77:            env->fsr |= FSR_NVA;
        !            78:        }
        !            79:     } else if (DT0 < DT1) {
        !            80:         T0 = FSR_FCC0 << FS;
        !            81:     } else if (DT0 > DT1) {
        !            82:         T0 = FSR_FCC1 << FS;
        !            83:     } else {
        !            84:         T0 = 0;
        !            85:     }
        !            86:     env->fsr |= T0;
        !            87: }
        !            88: 
        !            89: #ifdef TARGET_SPARC64
        !            90: #undef FS
        !            91: #define FS 22
        !            92: void do_fcmps_fcc1 (void)
        !            93: {
        !            94:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !            95:     if (isnan(FT0) || isnan(FT1)) {
        !            96:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !            97:        if (env->fsr & FSR_NVM) {
        !            98:            env->fsr |= T0;
        !            99:            raise_exception(TT_FP_EXCP);
        !           100:        } else {
        !           101:            env->fsr |= FSR_NVA;
        !           102:        }
        !           103:     } else if (FT0 < FT1) {
        !           104:         T0 = FSR_FCC0 << FS;
        !           105:     } else if (FT0 > FT1) {
        !           106:         T0 = FSR_FCC1 << FS;
        !           107:     } else {
        !           108:         T0 = 0;
        !           109:     }
        !           110:     env->fsr |= T0;
        !           111: }
        !           112: 
        !           113: void do_fcmpd_fcc1 (void)
        !           114: {
        !           115:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !           116:     if (isnan(DT0) || isnan(DT1)) {
        !           117:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !           118:        if (env->fsr & FSR_NVM) {
        !           119:            env->fsr |= T0;
        !           120:            raise_exception(TT_FP_EXCP);
        !           121:        } else {
        !           122:            env->fsr |= FSR_NVA;
        !           123:        }
        !           124:     } else if (DT0 < DT1) {
        !           125:         T0 = FSR_FCC0 << FS;
        !           126:     } else if (DT0 > DT1) {
        !           127:         T0 = FSR_FCC1 << FS;
        !           128:     } else {
        !           129:         T0 = 0;
        !           130:     }
        !           131:     env->fsr |= T0;
        !           132: }
        !           133: 
        !           134: #undef FS
        !           135: #define FS 24
        !           136: void do_fcmps_fcc2 (void)
        !           137: {
        !           138:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !           139:     if (isnan(FT0) || isnan(FT1)) {
        !           140:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !           141:        if (env->fsr & FSR_NVM) {
        !           142:            env->fsr |= T0;
        !           143:            raise_exception(TT_FP_EXCP);
        !           144:        } else {
        !           145:            env->fsr |= FSR_NVA;
        !           146:        }
        !           147:     } else if (FT0 < FT1) {
        !           148:         T0 = FSR_FCC0 << FS;
        !           149:     } else if (FT0 > FT1) {
        !           150:         T0 = FSR_FCC1 << FS;
        !           151:     } else {
        !           152:         T0 = 0;
        !           153:     }
        !           154:     env->fsr |= T0;
        !           155: }
        !           156: 
        !           157: void do_fcmpd_fcc2 (void)
        !           158: {
        !           159:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !           160:     if (isnan(DT0) || isnan(DT1)) {
        !           161:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !           162:        if (env->fsr & FSR_NVM) {
        !           163:            env->fsr |= T0;
        !           164:            raise_exception(TT_FP_EXCP);
        !           165:        } else {
        !           166:            env->fsr |= FSR_NVA;
        !           167:        }
        !           168:     } else if (DT0 < DT1) {
        !           169:         T0 = FSR_FCC0 << FS;
        !           170:     } else if (DT0 > DT1) {
        !           171:         T0 = FSR_FCC1 << FS;
        !           172:     } else {
        !           173:         T0 = 0;
        !           174:     }
        !           175:     env->fsr |= T0;
        !           176: }
        !           177: 
        !           178: #undef FS
        !           179: #define FS 26
        !           180: void do_fcmps_fcc3 (void)
        !           181: {
        !           182:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !           183:     if (isnan(FT0) || isnan(FT1)) {
        !           184:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !           185:        if (env->fsr & FSR_NVM) {
        !           186:            env->fsr |= T0;
        !           187:            raise_exception(TT_FP_EXCP);
        !           188:        } else {
        !           189:            env->fsr |= FSR_NVA;
        !           190:        }
        !           191:     } else if (FT0 < FT1) {
        !           192:         T0 = FSR_FCC0 << FS;
        !           193:     } else if (FT0 > FT1) {
        !           194:         T0 = FSR_FCC1 << FS;
        !           195:     } else {
        !           196:         T0 = 0;
        !           197:     }
        !           198:     env->fsr |= T0;
        !           199: }
        !           200: 
        !           201: void do_fcmpd_fcc3 (void)
        !           202: {
        !           203:     env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);
        !           204:     if (isnan(DT0) || isnan(DT1)) {
        !           205:         T0 = (FSR_FCC1 | FSR_FCC0) << FS;
        !           206:        if (env->fsr & FSR_NVM) {
        !           207:            env->fsr |= T0;
        !           208:            raise_exception(TT_FP_EXCP);
        !           209:        } else {
        !           210:            env->fsr |= FSR_NVA;
        !           211:        }
        !           212:     } else if (DT0 < DT1) {
        !           213:         T0 = FSR_FCC0 << FS;
        !           214:     } else if (DT0 > DT1) {
        !           215:         T0 = FSR_FCC1 << FS;
        !           216:     } else {
        !           217:         T0 = 0;
        !           218:     }
        !           219:     env->fsr |= T0;
        !           220: }
        !           221: #undef FS
        !           222: #endif
        !           223: 
        !           224: #ifndef TARGET_SPARC64
        !           225: void helper_ld_asi(int asi, int size, int sign)
        !           226: {
        !           227:     uint32_t ret = 0;
        !           228: 
        !           229:     switch (asi) {
        !           230:     case 3: /* MMU probe */
        !           231:        {
        !           232:            int mmulev;
        !           233: 
        !           234:            mmulev = (T0 >> 8) & 15;
        !           235:            if (mmulev > 4)
        !           236:                ret = 0;
        !           237:            else {
        !           238:                ret = mmu_probe(env, T0, mmulev);
        !           239:                //bswap32s(&ret);
        !           240:            }
        !           241: #ifdef DEBUG_MMU
        !           242:            printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);
        !           243: #endif
        !           244:        }
        !           245:        break;
        !           246:     case 4: /* read MMU regs */
        !           247:        {
        !           248:            int reg = (T0 >> 8) & 0xf;
        !           249:            
        !           250:            ret = env->mmuregs[reg];
        !           251:            if (reg == 3) /* Fault status cleared on read */
        !           252:                env->mmuregs[reg] = 0;
        !           253: #ifdef DEBUG_MMU
        !           254:            printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);
        !           255: #endif
        !           256:        }
        !           257:        break;
        !           258:     case 0x20 ... 0x2f: /* MMU passthrough */
        !           259:        cpu_physical_memory_read(T0, (void *) &ret, size);
        !           260:        if (size == 4)
        !           261:            tswap32s(&ret);
        !           262:         else if (size == 2)
        !           263:            tswap16s((uint16_t *)&ret);
        !           264:        break;
        !           265:     default:
        !           266:        ret = 0;
        !           267:        break;
        !           268:     }
        !           269:     T1 = ret;
        !           270: }
        !           271: 
        !           272: void helper_st_asi(int asi, int size, int sign)
        !           273: {
        !           274:     switch(asi) {
        !           275:     case 3: /* MMU flush */
        !           276:        {
        !           277:            int mmulev;
        !           278: 
        !           279:            mmulev = (T0 >> 8) & 15;
        !           280: #ifdef DEBUG_MMU
        !           281:            printf("mmu flush level %d\n", mmulev);
        !           282: #endif
        !           283:            switch (mmulev) {
        !           284:            case 0: // flush page
        !           285:                tlb_flush_page(env, T0 & 0xfffff000);
        !           286:                break;
        !           287:            case 1: // flush segment (256k)
        !           288:            case 2: // flush region (16M)
        !           289:            case 3: // flush context (4G)
        !           290:            case 4: // flush entire
        !           291:                tlb_flush(env, 1);
        !           292:                break;
        !           293:            default:
        !           294:                break;
        !           295:            }
        !           296: #ifdef DEBUG_MMU
        !           297:            dump_mmu(env);
        !           298: #endif
        !           299:            return;
        !           300:        }
        !           301:     case 4: /* write MMU regs */
        !           302:        {
        !           303:            int reg = (T0 >> 8) & 0xf;
        !           304:            uint32_t oldreg;
        !           305:            
        !           306:            oldreg = env->mmuregs[reg];
        !           307:             switch(reg) {
        !           308:             case 0:
        !           309:                env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
        !           310:                env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
        !           311:                // Mappings generated during no-fault mode or MMU
        !           312:                // disabled mode are invalid in normal mode
        !           313:                 if (oldreg != env->mmuregs[reg])
        !           314:                     tlb_flush(env, 1);
        !           315:                 break;
        !           316:             case 2:
        !           317:                env->mmuregs[reg] = T1;
        !           318:                 if (oldreg != env->mmuregs[reg]) {
        !           319:                     /* we flush when the MMU context changes because
        !           320:                        QEMU has no MMU context support */
        !           321:                     tlb_flush(env, 1);
        !           322:                 }
        !           323:                 break;
        !           324:             case 3:
        !           325:             case 4:
        !           326:                 break;
        !           327:             default:
        !           328:                env->mmuregs[reg] = T1;
        !           329:                 break;
        !           330:             }
        !           331: #ifdef DEBUG_MMU
        !           332:             if (oldreg != env->mmuregs[reg]) {
        !           333:                 printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);
        !           334:             }
        !           335:            dump_mmu(env);
        !           336: #endif
        !           337:            return;
        !           338:        }
        !           339:     case 0x17: /* Block copy, sta access */
        !           340:        {
        !           341:            // value (T1) = src
        !           342:            // address (T0) = dst
        !           343:            // copy 32 bytes
        !           344:            uint32_t src = T1, dst = T0;
        !           345:            uint8_t temp[32];
        !           346:            
        !           347:            tswap32s(&src);
        !           348: 
        !           349:            cpu_physical_memory_read(src, (void *) &temp, 32);
        !           350:            cpu_physical_memory_write(dst, (void *) &temp, 32);
        !           351:        }
        !           352:        return;
        !           353:     case 0x1f: /* Block fill, stda access */
        !           354:        {
        !           355:            // value (T1, T2)
        !           356:            // address (T0) = dst
        !           357:            // fill 32 bytes
        !           358:            int i;
        !           359:            uint32_t dst = T0;
        !           360:            uint64_t val;
        !           361:            
        !           362:            val = (((uint64_t)T1) << 32) | T2;
        !           363:            tswap64s(&val);
        !           364: 
        !           365:            for (i = 0; i < 32; i += 8, dst += 8) {
        !           366:                cpu_physical_memory_write(dst, (void *) &val, 8);
        !           367:            }
        !           368:        }
        !           369:        return;
        !           370:     case 0x20 ... 0x2f: /* MMU passthrough */
        !           371:        {
        !           372:            uint32_t temp = T1;
        !           373:            if (size == 4)
        !           374:                tswap32s(&temp);
        !           375:            else if (size == 2)
        !           376:                tswap16s((uint16_t *)&temp);
        !           377:            cpu_physical_memory_write(T0, (void *) &temp, size);
        !           378:        }
        !           379:        return;
        !           380:     default:
        !           381:        return;
        !           382:     }
        !           383: }
        !           384: 
        !           385: #else
        !           386: 
        !           387: void helper_ld_asi(int asi, int size, int sign)
        !           388: {
        !           389:     uint64_t ret = 0;
        !           390: 
        !           391:     if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
        !           392:        raise_exception(TT_PRIV_ACT);
        !           393: 
        !           394:     switch (asi) {
        !           395:     case 0x14: // Bypass
        !           396:     case 0x15: // Bypass, non-cacheable
        !           397:        {
        !           398:            cpu_physical_memory_read(T0, (void *) &ret, size);
        !           399:            if (size == 8)
        !           400:                tswap64s(&ret);
        !           401:            if (size == 4)
        !           402:                tswap32s((uint32_t *)&ret);
        !           403:            else if (size == 2)
        !           404:                tswap16s((uint16_t *)&ret);
        !           405:            break;
        !           406:        }
        !           407:     case 0x04: // Nucleus
        !           408:     case 0x0c: // Nucleus Little Endian (LE)
        !           409:     case 0x10: // As if user primary
        !           410:     case 0x11: // As if user secondary
        !           411:     case 0x18: // As if user primary LE
        !           412:     case 0x19: // As if user secondary LE
        !           413:     case 0x1c: // Bypass LE
        !           414:     case 0x1d: // Bypass, non-cacheable LE
        !           415:     case 0x24: // Nucleus quad LDD 128 bit atomic
        !           416:     case 0x2c: // Nucleus quad LDD 128 bit atomic
        !           417:     case 0x4a: // UPA config
        !           418:     case 0x82: // Primary no-fault
        !           419:     case 0x83: // Secondary no-fault
        !           420:     case 0x88: // Primary LE
        !           421:     case 0x89: // Secondary LE
        !           422:     case 0x8a: // Primary no-fault LE
        !           423:     case 0x8b: // Secondary no-fault LE
        !           424:        // XXX
        !           425:        break;
        !           426:     case 0x45: // LSU
        !           427:        ret = env->lsu;
        !           428:        break;
        !           429:     case 0x50: // I-MMU regs
        !           430:        {
        !           431:            int reg = (T0 >> 3) & 0xf;
        !           432: 
        !           433:            ret = env->immuregs[reg];
        !           434:            break;
        !           435:        }
        !           436:     case 0x51: // I-MMU 8k TSB pointer
        !           437:     case 0x52: // I-MMU 64k TSB pointer
        !           438:     case 0x55: // I-MMU data access
        !           439:        // XXX
        !           440:        break;
        !           441:     case 0x56: // I-MMU tag read
        !           442:        {
        !           443:            unsigned int i;
        !           444:            
        !           445:            for (i = 0; i < 64; i++) {
        !           446:                // Valid, ctx match, vaddr match
        !           447:                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&
        !           448:                    env->itlb_tag[i] == T0) {
        !           449:                    ret = env->itlb_tag[i];
        !           450:                    break;
        !           451:                }
        !           452:            }
        !           453:            break;
        !           454:        }
        !           455:     case 0x58: // D-MMU regs
        !           456:        {
        !           457:            int reg = (T0 >> 3) & 0xf;
        !           458: 
        !           459:            ret = env->dmmuregs[reg];
        !           460:            break;
        !           461:        }
        !           462:     case 0x5e: // D-MMU tag read
        !           463:        {
        !           464:            unsigned int i;
        !           465:            
        !           466:            for (i = 0; i < 64; i++) {
        !           467:                // Valid, ctx match, vaddr match
        !           468:                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&
        !           469:                    env->dtlb_tag[i] == T0) {
        !           470:                    ret = env->dtlb_tag[i];
        !           471:                    break;
        !           472:                }
        !           473:            }
        !           474:            break;
        !           475:        }
        !           476:     case 0x59: // D-MMU 8k TSB pointer
        !           477:     case 0x5a: // D-MMU 64k TSB pointer
        !           478:     case 0x5b: // D-MMU data pointer
        !           479:     case 0x5d: // D-MMU data access
        !           480:     case 0x48: // Interrupt dispatch, RO
        !           481:     case 0x49: // Interrupt data receive
        !           482:     case 0x7f: // Incoming interrupt vector, RO
        !           483:        // XXX
        !           484:        break;
        !           485:     case 0x54: // I-MMU data in, WO
        !           486:     case 0x57: // I-MMU demap, WO
        !           487:     case 0x5c: // D-MMU data in, WO
        !           488:     case 0x5f: // D-MMU demap, WO
        !           489:     case 0x77: // Interrupt vector, WO
        !           490:     default:
        !           491:        ret = 0;
        !           492:        break;
        !           493:     }
        !           494:     T1 = ret;
        !           495: }
        !           496: 
        !           497: void helper_st_asi(int asi, int size, int sign)
        !           498: {
        !           499:     if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)
        !           500:        raise_exception(TT_PRIV_ACT);
        !           501: 
        !           502:     switch(asi) {
        !           503:     case 0x14: // Bypass
        !           504:     case 0x15: // Bypass, non-cacheable
        !           505:        {
        !           506:            target_ulong temp = T1;
        !           507:            if (size == 8)
        !           508:                tswap64s(&temp);
        !           509:            else if (size == 4)
        !           510:                tswap32s((uint32_t *)&temp);
        !           511:            else if (size == 2)
        !           512:                tswap16s((uint16_t *)&temp);
        !           513:            cpu_physical_memory_write(T0, (void *) &temp, size);
        !           514:        }
        !           515:        return;
        !           516:     case 0x04: // Nucleus
        !           517:     case 0x0c: // Nucleus Little Endian (LE)
        !           518:     case 0x10: // As if user primary
        !           519:     case 0x11: // As if user secondary
        !           520:     case 0x18: // As if user primary LE
        !           521:     case 0x19: // As if user secondary LE
        !           522:     case 0x1c: // Bypass LE
        !           523:     case 0x1d: // Bypass, non-cacheable LE
        !           524:     case 0x24: // Nucleus quad LDD 128 bit atomic
        !           525:     case 0x2c: // Nucleus quad LDD 128 bit atomic
        !           526:     case 0x4a: // UPA config
        !           527:     case 0x88: // Primary LE
        !           528:     case 0x89: // Secondary LE
        !           529:        // XXX
        !           530:        return;
        !           531:     case 0x45: // LSU
        !           532:        {
        !           533:            uint64_t oldreg;
        !           534: 
        !           535:            oldreg = env->lsu;
        !           536:            env->lsu = T1 & (DMMU_E | IMMU_E);
        !           537:            // Mappings generated during D/I MMU disabled mode are
        !           538:            // invalid in normal mode
        !           539:            if (oldreg != env->lsu) {
        !           540: #ifdef DEBUG_MMU
        !           541:                 printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu);
        !           542:                dump_mmu(env);
        !           543: #endif
        !           544:                tlb_flush(env, 1);
        !           545:            }
        !           546:            return;
        !           547:        }
        !           548:     case 0x50: // I-MMU regs
        !           549:        {
        !           550:            int reg = (T0 >> 3) & 0xf;
        !           551:            uint64_t oldreg;
        !           552:            
        !           553:            oldreg = env->immuregs[reg];
        !           554:             switch(reg) {
        !           555:             case 0: // RO
        !           556:             case 4:
        !           557:                 return;
        !           558:             case 1: // Not in I-MMU
        !           559:             case 2:
        !           560:             case 7:
        !           561:             case 8:
        !           562:                 return;
        !           563:             case 3: // SFSR
        !           564:                if ((T1 & 1) == 0)
        !           565:                    T1 = 0; // Clear SFSR
        !           566:                 break;
        !           567:             case 5: // TSB access
        !           568:             case 6: // Tag access
        !           569:             default:
        !           570:                 break;
        !           571:             }
        !           572:            env->immuregs[reg] = T1;
        !           573: #ifdef DEBUG_MMU
        !           574:             if (oldreg != env->immuregs[reg]) {
        !           575:                 printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]);
        !           576:             }
        !           577:            dump_mmu(env);
        !           578: #endif
        !           579:            return;
        !           580:        }
        !           581:     case 0x54: // I-MMU data in
        !           582:        {
        !           583:            unsigned int i;
        !           584: 
        !           585:            // Try finding an invalid entry
        !           586:            for (i = 0; i < 64; i++) {
        !           587:                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {
        !           588:                    env->itlb_tag[i] = env->immuregs[6];
        !           589:                    env->itlb_tte[i] = T1;
        !           590:                    return;
        !           591:                }
        !           592:            }
        !           593:            // Try finding an unlocked entry
        !           594:            for (i = 0; i < 64; i++) {
        !           595:                if ((env->itlb_tte[i] & 0x40) == 0) {
        !           596:                    env->itlb_tag[i] = env->immuregs[6];
        !           597:                    env->itlb_tte[i] = T1;
        !           598:                    return;
        !           599:                }
        !           600:            }
        !           601:            // error state?
        !           602:            return;
        !           603:        }
        !           604:     case 0x55: // I-MMU data access
        !           605:        {
        !           606:            unsigned int i = (T0 >> 3) & 0x3f;
        !           607: 
        !           608:            env->itlb_tag[i] = env->immuregs[6];
        !           609:            env->itlb_tte[i] = T1;
        !           610:            return;
        !           611:        }
        !           612:     case 0x57: // I-MMU demap
        !           613:        // XXX
        !           614:        return;
        !           615:     case 0x58: // D-MMU regs
        !           616:        {
        !           617:            int reg = (T0 >> 3) & 0xf;
        !           618:            uint64_t oldreg;
        !           619:            
        !           620:            oldreg = env->dmmuregs[reg];
        !           621:             switch(reg) {
        !           622:             case 0: // RO
        !           623:             case 4:
        !           624:                 return;
        !           625:             case 3: // SFSR
        !           626:                if ((T1 & 1) == 0) {
        !           627:                    T1 = 0; // Clear SFSR, Fault address
        !           628:                    env->dmmuregs[4] = 0;
        !           629:                }
        !           630:                env->dmmuregs[reg] = T1;
        !           631:                 break;
        !           632:             case 1: // Primary context
        !           633:             case 2: // Secondary context
        !           634:             case 5: // TSB access
        !           635:             case 6: // Tag access
        !           636:             case 7: // Virtual Watchpoint
        !           637:             case 8: // Physical Watchpoint
        !           638:             default:
        !           639:                 break;
        !           640:             }
        !           641:            env->dmmuregs[reg] = T1;
        !           642: #ifdef DEBUG_MMU
        !           643:             if (oldreg != env->dmmuregs[reg]) {
        !           644:                 printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]);
        !           645:             }
        !           646:            dump_mmu(env);
        !           647: #endif
        !           648:            return;
        !           649:        }
        !           650:     case 0x5c: // D-MMU data in
        !           651:        {
        !           652:            unsigned int i;
        !           653: 
        !           654:            // Try finding an invalid entry
        !           655:            for (i = 0; i < 64; i++) {
        !           656:                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {
        !           657:                    env->dtlb_tag[i] = env->dmmuregs[6];
        !           658:                    env->dtlb_tte[i] = T1;
        !           659:                    return;
        !           660:                }
        !           661:            }
        !           662:            // Try finding an unlocked entry
        !           663:            for (i = 0; i < 64; i++) {
        !           664:                if ((env->dtlb_tte[i] & 0x40) == 0) {
        !           665:                    env->dtlb_tag[i] = env->dmmuregs[6];
        !           666:                    env->dtlb_tte[i] = T1;
        !           667:                    return;
        !           668:                }
        !           669:            }
        !           670:            // error state?
        !           671:            return;
        !           672:        }
        !           673:     case 0x5d: // D-MMU data access
        !           674:        {
        !           675:            unsigned int i = (T0 >> 3) & 0x3f;
        !           676: 
        !           677:            env->dtlb_tag[i] = env->dmmuregs[6];
        !           678:            env->dtlb_tte[i] = T1;
        !           679:            return;
        !           680:        }
        !           681:     case 0x5f: // D-MMU demap
        !           682:     case 0x49: // Interrupt data receive
        !           683:        // XXX
        !           684:        return;
        !           685:     case 0x51: // I-MMU 8k TSB pointer, RO
        !           686:     case 0x52: // I-MMU 64k TSB pointer, RO
        !           687:     case 0x56: // I-MMU tag read, RO
        !           688:     case 0x59: // D-MMU 8k TSB pointer, RO
        !           689:     case 0x5a: // D-MMU 64k TSB pointer, RO
        !           690:     case 0x5b: // D-MMU data pointer, RO
        !           691:     case 0x5e: // D-MMU tag read, RO
        !           692:     case 0x48: // Interrupt dispatch, RO
        !           693:     case 0x7f: // Incoming interrupt vector, RO
        !           694:     case 0x82: // Primary no-fault, RO
        !           695:     case 0x83: // Secondary no-fault, RO
        !           696:     case 0x8a: // Primary no-fault LE, RO
        !           697:     case 0x8b: // Secondary no-fault LE, RO
        !           698:     default:
        !           699:        return;
        !           700:     }
        !           701: }
        !           702: 
        !           703: #endif
        !           704: 
        !           705: #ifndef TARGET_SPARC64
        !           706: void helper_rett()
        !           707: {
        !           708:     unsigned int cwp;
        !           709: 
        !           710:     env->psret = 1;
        !           711:     cwp = (env->cwp + 1) & (NWINDOWS - 1); 
        !           712:     if (env->wim & (1 << cwp)) {
        !           713:         raise_exception(TT_WIN_UNF);
        !           714:     }
        !           715:     set_cwp(cwp);
        !           716:     env->psrs = env->psrps;
        !           717: }
        !           718: #endif
        !           719: 
        !           720: void helper_ldfsr(void)
        !           721: {
        !           722:     int rnd_mode;
        !           723:     switch (env->fsr & FSR_RD_MASK) {
        !           724:     case FSR_RD_NEAREST:
        !           725:         rnd_mode = float_round_nearest_even;
        !           726:        break;
        !           727:     default:
        !           728:     case FSR_RD_ZERO:
        !           729:         rnd_mode = float_round_to_zero;
        !           730:        break;
        !           731:     case FSR_RD_POS:
        !           732:         rnd_mode = float_round_up;
        !           733:        break;
        !           734:     case FSR_RD_NEG:
        !           735:         rnd_mode = float_round_down;
        !           736:        break;
        !           737:     }
        !           738:     set_float_rounding_mode(rnd_mode, &env->fp_status);
        !           739: }
        !           740: 
        !           741: void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f)
        !           742: {
        !           743:     int exptemp;
        !           744: 
        !           745:     *pmant = ldexp(frexp(f, &exptemp), 53);
        !           746:     *pexp = exptemp;
        !           747: }
        !           748: 
        !           749: double cpu_put_fp64(uint64_t mant, uint16_t exp)
        !           750: {
        !           751:     return ldexp((double) mant, exp - 53);
        !           752: }
        !           753: 
        !           754: void helper_debug()
        !           755: {
        !           756:     env->exception_index = EXCP_DEBUG;
        !           757:     cpu_loop_exit();
        !           758: }
        !           759: 
        !           760: #ifndef TARGET_SPARC64
        !           761: void do_wrpsr()
        !           762: {
        !           763:     PUT_PSR(env, T0);
        !           764: }
        !           765: 
        !           766: void do_rdpsr()
        !           767: {
        !           768:     T0 = GET_PSR(env);
        !           769: }
        !           770: 
        !           771: #else
        !           772: 
        !           773: void do_popc()
        !           774: {
        !           775:     T0 = (T1 & 0x5555555555555555ULL) + ((T1 >> 1) & 0x5555555555555555ULL);
        !           776:     T0 = (T0 & 0x3333333333333333ULL) + ((T0 >> 2) & 0x3333333333333333ULL);
        !           777:     T0 = (T0 & 0x0f0f0f0f0f0f0f0fULL) + ((T0 >> 4) & 0x0f0f0f0f0f0f0f0fULL);
        !           778:     T0 = (T0 & 0x00ff00ff00ff00ffULL) + ((T0 >> 8) & 0x00ff00ff00ff00ffULL);
        !           779:     T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL);
        !           780:     T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL);
        !           781: }
        !           782: 
        !           783: static inline uint64_t *get_gregset(uint64_t pstate)
        !           784: {
        !           785:     switch (pstate) {
        !           786:     default:
        !           787:     case 0:
        !           788:        return env->bgregs;
        !           789:     case PS_AG:
        !           790:        return env->agregs;
        !           791:     case PS_MG:
        !           792:        return env->mgregs;
        !           793:     case PS_IG:
        !           794:        return env->igregs;
        !           795:     }
        !           796: }
        !           797: 
        !           798: void do_wrpstate()
        !           799: {
        !           800:     uint64_t new_pstate, pstate_regs, new_pstate_regs;
        !           801:     uint64_t *src, *dst;
        !           802: 
        !           803:     new_pstate = T0 & 0xf3f;
        !           804:     pstate_regs = env->pstate & 0xc01;
        !           805:     new_pstate_regs = new_pstate & 0xc01;
        !           806:     if (new_pstate_regs != pstate_regs) {
        !           807:        // Switch global register bank
        !           808:        src = get_gregset(new_pstate_regs);
        !           809:        dst = get_gregset(pstate_regs);
        !           810:        memcpy32(dst, env->gregs);
        !           811:        memcpy32(env->gregs, src);
        !           812:     }
        !           813:     env->pstate = new_pstate;
        !           814: }
        !           815: 
        !           816: void do_done(void)
        !           817: {
        !           818:     env->tl--;
        !           819:     env->pc = env->tnpc[env->tl];
        !           820:     env->npc = env->tnpc[env->tl] + 4;
        !           821:     PUT_CCR(env, env->tstate[env->tl] >> 32);
        !           822:     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
        !           823:     env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
        !           824:     set_cwp(env->tstate[env->tl] & 0xff);
        !           825: }
        !           826: 
        !           827: void do_retry(void)
        !           828: {
        !           829:     env->tl--;
        !           830:     env->pc = env->tpc[env->tl];
        !           831:     env->npc = env->tnpc[env->tl];
        !           832:     PUT_CCR(env, env->tstate[env->tl] >> 32);
        !           833:     env->asi = (env->tstate[env->tl] >> 24) & 0xff;
        !           834:     env->pstate = (env->tstate[env->tl] >> 8) & 0xfff;
        !           835:     set_cwp(env->tstate[env->tl] & 0xff);
        !           836: }
        !           837: #endif
        !           838: 
        !           839: void set_cwp(int new_cwp)
        !           840: {
        !           841:     /* put the modified wrap registers at their proper location */
        !           842:     if (env->cwp == (NWINDOWS - 1))
        !           843:         memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
        !           844:     env->cwp = new_cwp;
        !           845:     /* put the wrap registers at their temporary location */
        !           846:     if (new_cwp == (NWINDOWS - 1))
        !           847:         memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
        !           848:     env->regwptr = env->regbase + (new_cwp * 16);
        !           849:     REGWPTR = env->regwptr;
        !           850: }
        !           851: 
        !           852: void cpu_set_cwp(CPUState *env1, int new_cwp)
        !           853: {
        !           854:     CPUState *saved_env;
        !           855: #ifdef reg_REGWPTR
        !           856:     target_ulong *saved_regwptr;
        !           857: #endif
        !           858: 
        !           859:     saved_env = env;
        !           860: #ifdef reg_REGWPTR
        !           861:     saved_regwptr = REGWPTR;
        !           862: #endif
        !           863:     env = env1;
        !           864:     set_cwp(new_cwp);
        !           865:     env = saved_env;
        !           866: #ifdef reg_REGWPTR
        !           867:     REGWPTR = saved_regwptr;
        !           868: #endif
        !           869: }
        !           870: 
        !           871: #ifdef TARGET_SPARC64
        !           872: void do_interrupt(int intno)
        !           873: {
        !           874: #ifdef DEBUG_PCALL
        !           875:     if (loglevel & CPU_LOG_INT) {
        !           876:        static int count;
        !           877:        fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n",
        !           878:                 count, intno,
        !           879:                 env->pc,
        !           880:                 env->npc, env->regwptr[6]);
        !           881:        cpu_dump_state(env, logfile, fprintf, 0);
        !           882: #if 0
        !           883:        {
        !           884:            int i;
        !           885:            uint8_t *ptr;
        !           886: 
        !           887:            fprintf(logfile, "       code=");
        !           888:            ptr = (uint8_t *)env->pc;
        !           889:            for(i = 0; i < 16; i++) {
        !           890:                fprintf(logfile, " %02x", ldub(ptr + i));
        !           891:            }
        !           892:            fprintf(logfile, "\n");
        !           893:        }
        !           894: #endif
        !           895:        count++;
        !           896:     }
        !           897: #endif
        !           898: #if !defined(CONFIG_USER_ONLY) 
        !           899:     if (env->tl == MAXTL) {
        !           900:         cpu_abort(cpu_single_env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index);
        !           901:        return;
        !           902:     }
        !           903: #endif
        !           904:     env->tstate[env->tl] = ((uint64_t)GET_CCR(env) << 32) | ((env->asi & 0xff) << 24) |
        !           905:        ((env->pstate & 0xfff) << 8) | (env->cwp & 0xff);
        !           906:     env->tpc[env->tl] = env->pc;
        !           907:     env->tnpc[env->tl] = env->npc;
        !           908:     env->tt[env->tl] = intno;
        !           909:     env->pstate = PS_PEF | PS_PRIV | PS_AG;
        !           910:     env->tbr &= ~0x7fffULL;
        !           911:     env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
        !           912:     if (env->tl < MAXTL - 1) {
        !           913:        env->tl++;
        !           914:     } else {
        !           915:        env->pstate |= PS_RED;
        !           916:        if (env->tl != MAXTL)
        !           917:            env->tl++;
        !           918:     }
        !           919:     env->pc = env->tbr;
        !           920:     env->npc = env->pc + 4;
        !           921:     env->exception_index = 0;
        !           922: }
        !           923: #else
        !           924: void do_interrupt(int intno)
        !           925: {
        !           926:     int cwp;
        !           927: 
        !           928: #ifdef DEBUG_PCALL
        !           929:     if (loglevel & CPU_LOG_INT) {
        !           930:        static int count;
        !           931:        fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n",
        !           932:                 count, intno,
        !           933:                 env->pc,
        !           934:                 env->npc, env->regwptr[6]);
        !           935:        cpu_dump_state(env, logfile, fprintf, 0);
        !           936: #if 0
        !           937:        {
        !           938:            int i;
        !           939:            uint8_t *ptr;
        !           940: 
        !           941:            fprintf(logfile, "       code=");
        !           942:            ptr = (uint8_t *)env->pc;
        !           943:            for(i = 0; i < 16; i++) {
        !           944:                fprintf(logfile, " %02x", ldub(ptr + i));
        !           945:            }
        !           946:            fprintf(logfile, "\n");
        !           947:        }
        !           948: #endif
        !           949:        count++;
        !           950:     }
        !           951: #endif
        !           952: #if !defined(CONFIG_USER_ONLY) 
        !           953:     if (env->psret == 0) {
        !           954:         cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index);
        !           955:        return;
        !           956:     }
        !           957: #endif
        !           958:     env->psret = 0;
        !           959:     cwp = (env->cwp - 1) & (NWINDOWS - 1); 
        !           960:     set_cwp(cwp);
        !           961:     env->regwptr[9] = env->pc;
        !           962:     env->regwptr[10] = env->npc;
        !           963:     env->psrps = env->psrs;
        !           964:     env->psrs = 1;
        !           965:     env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
        !           966:     env->pc = env->tbr;
        !           967:     env->npc = env->pc + 4;
        !           968:     env->exception_index = 0;
        !           969: }
        !           970: #endif
        !           971: 
        !           972: #if !defined(CONFIG_USER_ONLY) 
        !           973: 
        !           974: #define MMUSUFFIX _mmu
        !           975: #define GETPC() (__builtin_return_address(0))
        !           976: 
        !           977: #define SHIFT 0
        !           978: #include "softmmu_template.h"
        !           979: 
        !           980: #define SHIFT 1
        !           981: #include "softmmu_template.h"
        !           982: 
        !           983: #define SHIFT 2
        !           984: #include "softmmu_template.h"
        !           985: 
        !           986: #define SHIFT 3
        !           987: #include "softmmu_template.h"
        !           988: 
        !           989: 
        !           990: /* try to fill the TLB and return an exception if error. If retaddr is
        !           991:    NULL, it means that the function was called in C code (i.e. not
        !           992:    from generated code or from helper.c) */
        !           993: /* XXX: fix it to restore all registers */
        !           994: void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
        !           995: {
        !           996:     TranslationBlock *tb;
        !           997:     int ret;
        !           998:     unsigned long pc;
        !           999:     CPUState *saved_env;
        !          1000: 
        !          1001:     /* XXX: hack to restore env in all cases, even if not called from
        !          1002:        generated code */
        !          1003:     saved_env = env;
        !          1004:     env = cpu_single_env;
        !          1005: 
        !          1006:     ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
        !          1007:     if (ret) {
        !          1008:         if (retaddr) {
        !          1009:             /* now we have a real cpu fault */
        !          1010:             pc = (unsigned long)retaddr;
        !          1011:             tb = tb_find_pc(pc);
        !          1012:             if (tb) {
        !          1013:                 /* the PC is inside the translated code. It means that we have
        !          1014:                    a virtual CPU fault */
        !          1015:                 cpu_restore_state(tb, env, pc, (void *)T2);
        !          1016:             }
        !          1017:         }
        !          1018:         cpu_loop_exit();
        !          1019:     }
        !          1020:     env = saved_env;
        !          1021: }
        !          1022: 
        !          1023: #endif

unix.superglobalmegacorp.com

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