Annotation of previous/src/cpu/cpuemu_common.c, revision 1.1

1.1     ! root        1: 
        !             2: 
        !             3: #include "sysconfig.h"
        !             4: #include "sysdeps.h"
        !             5: 
        !             6: #define MOVEC_DEBUG 0
        !             7: 
        !             8: #include "options_cpu.h"
        !             9: #include "memory.h"
        !            10: #include "newcpu.h"
        !            11: #include "cpummu.h"
        !            12: #include "cpummu030.h"
        !            13: #include "cpu_prefetch.h"
        !            14: 
        !            15: #include "log.h"
        !            16: 
        !            17: void val_move2c2 (int regno, uae_u32 val)
        !            18: {
        !            19:        switch (regno) {
        !            20:        case 0: regs.sfc = val; break;
        !            21:        case 1: regs.dfc = val; break;
        !            22:        case 2: regs.cacr = val; break;
        !            23:        case 3: regs.tcr = val; break;
        !            24:        case 4: regs.itt0 = val; break;
        !            25:        case 5: regs.itt1 = val; break;
        !            26:        case 6: regs.dtt0 = val; break;
        !            27:        case 7: regs.dtt1 = val; break;
        !            28:        case 8: regs.buscr = val; break;
        !            29:        case 0x800: regs.usp = val; break;
        !            30:        case 0x801: regs.vbr = val; break;
        !            31:        case 0x802: regs.caar = val; break;
        !            32:        case 0x803: regs.msp = val; break;
        !            33:        case 0x804: regs.isp = val; break;
        !            34:        case 0x805: regs.mmusr = val; break;
        !            35:        case 0x806: regs.urp = val; break;
        !            36:        case 0x807: regs.srp = val; break;
        !            37:        case 0x808: regs.pcr = val; break;
        !            38:        }
        !            39: }
        !            40: 
        !            41: uae_u32 val_move2c (int regno)
        !            42: {
        !            43:        switch (regno) {
        !            44:        case 0: return regs.sfc;
        !            45:        case 1: return regs.dfc;
        !            46:        case 2: return regs.cacr;
        !            47:        case 3: return regs.tcr;
        !            48:        case 4: return regs.itt0;
        !            49:        case 5: return regs.itt1;
        !            50:        case 6: return regs.dtt0;
        !            51:        case 7: return regs.dtt1;
        !            52:        case 8: return regs.buscr;
        !            53:        case 0x800: return regs.usp;
        !            54:        case 0x801: return regs.vbr;
        !            55:        case 0x802: return regs.caar;
        !            56:        case 0x803: return regs.msp;
        !            57:        case 0x804: return regs.isp;
        !            58:        case 0x805: return regs.mmusr;
        !            59:        case 0x806: return regs.urp;
        !            60:        case 0x807: return regs.srp;
        !            61:        case 0x808: return regs.pcr;
        !            62:        default: return 0;
        !            63:        }
        !            64: }
        !            65: 
        !            66: 
        !            67: #ifndef CPUEMU_68000_ONLY
        !            68: 
        !            69: int movec_illg (int regno)
        !            70: {
        !            71:        int regno2 = regno & 0x7ff;
        !            72: 
        !            73:        if (currprefs.cpu_model == 68060) {
        !            74:                if (regno <= 8)
        !            75:                        return 0;
        !            76:                if (regno == 0x800 || regno == 0x801 ||
        !            77:                        regno == 0x806 || regno == 0x807 || regno == 0x808)
        !            78:                        return 0;
        !            79:                return 1;
        !            80:        } else if (currprefs.cpu_model == 68010) {
        !            81:                if (regno2 < 2)
        !            82:                        return 0;
        !            83:                return 1;
        !            84:        } else if (currprefs.cpu_model == 68020) {
        !            85:                if (regno == 3)
        !            86:                        return 1; /* 68040/060 only */
        !            87:                /* 4 is >=68040, but 0x804 is in 68020 */
        !            88:                if (regno2 < 4 || regno == 0x804)
        !            89:                        return 0;
        !            90:                return 1;
        !            91:        } else if (currprefs.cpu_model == 68030) {
        !            92:                if (regno2 <= 2)
        !            93:                        return 0;
        !            94:                if (regno == 0x803 || regno == 0x804)
        !            95:                        return 0;
        !            96:                return 1;
        !            97:        } else if (currprefs.cpu_model == 68040) {
        !            98:                if (regno == 0x802)
        !            99:                        return 1; /* 68020/030 only */
        !           100:                if (regno2 < 8) return 0;
        !           101:                return 1;
        !           102:        }
        !           103:        return 1;
        !           104: }
        !           105: 
        !           106: int m68k_move2c (int regno, uae_u32 *regp)
        !           107: {
        !           108: #if MOVEC_DEBUG > 0
        !           109:        write_log (_T("move2c %04X <- %08X PC=%x\n"), regno, *regp, M68K_GETPC);
        !           110: #endif
        !           111:        if (movec_illg (regno)) {
        !           112:                op_illg (0x4E7B);
        !           113:                return 0;
        !           114:        } else {
        !           115:                switch (regno) {
        !           116:                case 0: regs.sfc = *regp & 7; break;
        !           117:                case 1: regs.dfc = *regp & 7; break;
        !           118:                case 2:
        !           119:                        {
        !           120:                                uae_u32 cacr_mask = 0;
        !           121:                                if (currprefs.cpu_model == 68020)
        !           122:                                        cacr_mask = 0x0000000f;
        !           123:                                else if (currprefs.cpu_model == 68030)
        !           124:                                        cacr_mask = 0x00003f1f;
        !           125:                                else if (currprefs.cpu_model == 68040)
        !           126:                                        cacr_mask = 0x80008000;
        !           127:                                else if (currprefs.cpu_model == 68060)
        !           128:                                        cacr_mask = 0xf8e0e000;
        !           129:                                regs.cacr = *regp & cacr_mask;
        !           130:                                set_cpu_caches (false);
        !           131:                        }
        !           132:                        break;
        !           133:                        /* 68040/060 only */
        !           134:                case 3:
        !           135:                        regs.tcr = *regp & (currprefs.cpu_model == 68060 ? 0xfffe : 0xc000);
        !           136:                        if (currprefs.mmu_model)
        !           137:                                mmu_set_tc (regs.tcr);
        !           138:                        break;
        !           139: 
        !           140:                        /* no differences between 68040 and 68060 */
        !           141:                case 4: regs.itt0 = *regp & 0xffffe364; mmu_tt_modified (); break;
        !           142:                case 5: regs.itt1 = *regp & 0xffffe364; mmu_tt_modified (); break;
        !           143:                case 6: regs.dtt0 = *regp & 0xffffe364; mmu_tt_modified (); break;
        !           144:                case 7: regs.dtt1 = *regp & 0xffffe364; mmu_tt_modified (); break;
        !           145:                        /* 68060 only */
        !           146:                case 8: regs.buscr = *regp & 0xf0000000; break;
        !           147: 
        !           148:                case 0x800: regs.usp = *regp; break;
        !           149:                case 0x801: regs.vbr = *regp; break;
        !           150:                case 0x802: regs.caar = *regp; break;
        !           151:                case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (regs, 7) = regs.msp; break;
        !           152:                case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (regs, 7) = regs.isp; break;
        !           153:                        /* 68040 only */
        !           154:                case 0x805: regs.mmusr = *regp; break;
        !           155:                        /* 68040/060 */
        !           156:                case 0x806: regs.urp = *regp & 0xfffffe00; break;
        !           157:                case 0x807: regs.srp = *regp & 0xfffffe00; break;
        !           158:                        /* 68060 only */
        !           159:                case 0x808:
        !           160:                        {
        !           161:                                uae_u32 opcr = regs.pcr;
        !           162:                                regs.pcr &= ~(0x40 | 2 | 1);
        !           163:                                regs.pcr |= (*regp) & (0x40 | 2 | 1);
        !           164:                                if (currprefs.fpu_model <= 0)
        !           165:                                        regs.pcr |= 2;
        !           166:                                if (((opcr ^ regs.pcr) & 2) == 2) {
        !           167:                                        //write_log (_T("68060 FPU state: %s\n"), regs.pcr & 2 ? _T("disabled") : _T("enabled"));
        !           168:                                        /* flush possible already translated FPU instructions */
        !           169:                                        flush_icache (0, 3);
        !           170:                                }
        !           171:                        }
        !           172:                        break;
        !           173:                default:
        !           174:                        op_illg (0x4E7B);
        !           175:                        return 0;
        !           176:                }
        !           177:        }
        !           178:        return 1;
        !           179: }
        !           180: 
        !           181: int m68k_movec2 (int regno, uae_u32 *regp)
        !           182: {
        !           183: #if MOVEC_DEBUG > 0
        !           184:        write_log (_T("movec2 %04X PC=%x\n"), regno, M68K_GETPC);
        !           185: #endif
        !           186:        if (movec_illg (regno)) {
        !           187:                op_illg (0x4E7A);
        !           188:                return 0;
        !           189:        } else {
        !           190:                switch (regno) {
        !           191:                case 0: *regp = regs.sfc; break;
        !           192:                case 1: *regp = regs.dfc; break;
        !           193:                case 2:
        !           194:                        {
        !           195:                                uae_u32 v = regs.cacr;
        !           196:                                uae_u32 cacr_mask = 0;
        !           197:                                if (currprefs.cpu_model == 68020)
        !           198:                                        cacr_mask = 0x00000003;
        !           199:                                else if (currprefs.cpu_model == 68030)
        !           200:                                        cacr_mask = 0x00003313;
        !           201:                                else if (currprefs.cpu_model == 68040)
        !           202:                                        cacr_mask = 0x80008000;
        !           203:                                else if (currprefs.cpu_model == 68060)
        !           204:                                        cacr_mask = 0xf880e000;
        !           205:                                *regp = v & cacr_mask;
        !           206:                        }
        !           207:                        break;
        !           208:                case 3: *regp = regs.tcr; break;
        !           209:                case 4: *regp = regs.itt0; break;
        !           210:                case 5: *regp = regs.itt1; break;
        !           211:                case 6: *regp = regs.dtt0; break;
        !           212:                case 7: *regp = regs.dtt1; break;
        !           213:                case 8: *regp = regs.buscr; break;
        !           214: 
        !           215:                case 0x800: *regp = regs.usp; break;
        !           216:                case 0x801: *regp = regs.vbr; break;
        !           217:                case 0x802: *regp = regs.caar; break;
        !           218:                case 0x803: *regp = regs.m == 1 ? m68k_areg (regs, 7) : regs.msp; break;
        !           219:                case 0x804: *regp = regs.m == 0 ? m68k_areg (regs, 7) : regs.isp; break;
        !           220:                case 0x805: *regp = regs.mmusr; break;
        !           221:                case 0x806: *regp = regs.urp; break;
        !           222:                case 0x807: *regp = regs.srp; break;
        !           223:                case 0x808: *regp = regs.pcr; break;
        !           224: 
        !           225:                default:
        !           226:                        op_illg (0x4E7A);
        !           227:                        return 0;
        !           228:                }
        !           229:        }
        !           230: #if MOVEC_DEBUG > 0
        !           231:        write_log (_T("-> %08X\n"), *regp);
        !           232: #endif
        !           233:        return 1;
        !           234: }
        !           235: 
        !           236: #endif
        !           237: 
        !           238: /*
        !           239: * extract bitfield data from memory and return it in the MSBs
        !           240: * bdata caches the unmodified data for put_bitfield()
        !           241: */
        !           242: uae_u32 REGPARAM2 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
        !           243: {
        !           244:        uae_u32 tmp, res, mask;
        !           245: 
        !           246:        offset &= 7;
        !           247:        mask = 0xffffffffu << (32 - width);
        !           248:        switch ((offset + width + 7) >> 3) {
        !           249:        case 1:
        !           250:                tmp = get_byte (src);
        !           251:                res = tmp << (24 + offset);
        !           252:                bdata[0] = tmp & ~(mask >> (24 + offset));
        !           253:                break;
        !           254:        case 2:
        !           255:                tmp = get_word (src);
        !           256:                res = tmp << (16 + offset);
        !           257:                bdata[0] = tmp & ~(mask >> (16 + offset));
        !           258:                break;
        !           259:        case 3:
        !           260:                tmp = get_word (src);
        !           261:                res = tmp << (16 + offset);
        !           262:                bdata[0] = tmp & ~(mask >> (16 + offset));
        !           263:                tmp = get_byte (src + 2);
        !           264:                res |= tmp << (8 + offset);
        !           265:                bdata[1] = tmp & ~(mask >> (8 + offset));
        !           266:                break;
        !           267:        case 4:
        !           268:                tmp = get_long (src);
        !           269:                res = tmp << offset;
        !           270:                bdata[0] = tmp & ~(mask >> offset);
        !           271:                break;
        !           272:        case 5:
        !           273:                tmp = get_long (src);
        !           274:                res = tmp << offset;
        !           275:                bdata[0] = tmp & ~(mask >> offset);
        !           276:                tmp = get_byte (src + 4);
        !           277:                res |= tmp >> (8 - offset);
        !           278:                bdata[1] = tmp & ~(mask << (8 - offset));
        !           279:                break;
        !           280:        default:
        !           281:                /* Panic? */
        !           282:                //write_log (_T("get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
        !           283:                res = 0;
        !           284:                break;
        !           285:        }
        !           286:        return res;
        !           287: }
        !           288: /*
        !           289: * write bitfield data (in the LSBs) back to memory, upper bits
        !           290: * must be cleared already.
        !           291: */
        !           292: void REGPARAM2 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
        !           293: {
        !           294:        offset = (offset & 7) + width;
        !           295:        switch ((offset + 7) >> 3) {
        !           296:        case 1:
        !           297:                put_byte (dst, bdata[0] | (val << (8 - offset)));
        !           298:                break;
        !           299:        case 2:
        !           300:                put_word (dst, bdata[0] | (val << (16 - offset)));
        !           301:                break;
        !           302:        case 3:
        !           303:                put_word (dst, bdata[0] | (val >> (offset - 16)));
        !           304:                put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
        !           305:                break;
        !           306:        case 4:
        !           307:                put_long (dst, bdata[0] | (val << (32 - offset)));
        !           308:                break;
        !           309:        case 5:
        !           310:                put_long (dst, bdata[0] | (val >> (offset - 32)));
        !           311:                put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
        !           312:                break;
        !           313:        default:
        !           314:                //write_log (_T("put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
        !           315:                break;
        !           316:        }
        !           317: }
        !           318: 
        !           319: uae_u32 REGPARAM2 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
        !           320: {
        !           321:        uae_u32 tmp1, tmp2, res, mask;
        !           322: 
        !           323:        offset &= 7;
        !           324:        mask = 0xffffffffu << (32 - width);
        !           325:        switch ((offset + width + 7) >> 3) {
        !           326:        case 1:
        !           327:                tmp1 = x_cp_get_byte (src);
        !           328:                res = tmp1 << (24 + offset);
        !           329:                bdata[0] = tmp1 & ~(mask >> (24 + offset));
        !           330:                break;
        !           331:        case 2:
        !           332:                tmp1 = x_cp_get_word (src);
        !           333:                res = tmp1 << (16 + offset);
        !           334:                bdata[0] = tmp1 & ~(mask >> (16 + offset));
        !           335:                break;
        !           336:        case 3:
        !           337:                tmp1 = x_cp_get_word (src);
        !           338:                tmp2 = x_cp_get_byte (src + 2);
        !           339:                res = tmp1 << (16 + offset);
        !           340:                bdata[0] = tmp1 & ~(mask >> (16 + offset));
        !           341:                res |= tmp2 << (8 + offset);
        !           342:                bdata[1] = tmp2 & ~(mask >> (8 + offset));
        !           343:                break;
        !           344:        case 4:
        !           345:                tmp1 = x_cp_get_long (src);
        !           346:                res = tmp1 << offset;
        !           347:                bdata[0] = tmp1 & ~(mask >> offset);
        !           348:                break;
        !           349:        case 5:
        !           350:                tmp1 = x_cp_get_long (src);
        !           351:                tmp2 = x_cp_get_byte (src + 4);
        !           352:                res = tmp1 << offset;
        !           353:                bdata[0] = tmp1 & ~(mask >> offset);
        !           354:                res |= tmp2 >> (8 - offset);
        !           355:                bdata[1] = tmp2 & ~(mask << (8 - offset));
        !           356:                break;
        !           357:        default:
        !           358:                /* Panic? */
        !           359:                //write_log (_T("x_get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
        !           360:                res = 0;
        !           361:                break;
        !           362:        }
        !           363:        return res;
        !           364: }
        !           365: 
        !           366: void REGPARAM2 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
        !           367: {
        !           368:        offset = (offset & 7) + width;
        !           369:        switch ((offset + 7) >> 3) {
        !           370:        case 1:
        !           371:                x_cp_put_byte (dst, bdata[0] | (val << (8 - offset)));
        !           372:                break;
        !           373:        case 2:
        !           374:                x_cp_put_word (dst, bdata[0] | (val << (16 - offset)));
        !           375:                break;
        !           376:        case 3:
        !           377:                x_cp_put_word (dst, bdata[0] | (val >> (offset - 16)));
        !           378:                x_cp_put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
        !           379:                break;
        !           380:        case 4:
        !           381:                x_cp_put_long (dst, bdata[0] | (val << (32 - offset)));
        !           382:                break;
        !           383:        case 5:
        !           384:                x_cp_put_long (dst, bdata[0] | (val >> (offset - 32)));
        !           385:                x_cp_put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
        !           386:                break;
        !           387:        default:
        !           388:                //write_log (_T("x_put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
        !           389:                break;
        !           390:        }
        !           391: }
        !           392: 
        !           393: uae_u32 REGPARAM2 get_disp_ea_020 (uae_u32 base, int idx)
        !           394: {
        !           395:        uae_u16 dp = next_iword ();
        !           396:        int reg = (dp >> 12) & 15;
        !           397:        uae_s32 regd = regs.regs[reg];
        !           398:        if ((dp & 0x800) == 0)
        !           399:                regd = (uae_s32)(uae_s16)regd;
        !           400:        regd <<= (dp >> 9) & 3;
        !           401:        if (dp & 0x100) {
        !           402:                uae_s32 outer = 0;
        !           403:                if (dp & 0x80) base = 0;
        !           404:                if (dp & 0x40) regd = 0;
        !           405: 
        !           406:                if ((dp & 0x30) == 0x20)
        !           407:                        base += (uae_s32)(uae_s16) next_iword ();
        !           408:                if ((dp & 0x30) == 0x30)
        !           409:                        base += next_ilong ();
        !           410: 
        !           411:                if ((dp & 0x3) == 0x2)
        !           412:                        outer = (uae_s32)(uae_s16) next_iword ();
        !           413:                if ((dp & 0x3) == 0x3)
        !           414:                        outer = next_ilong ();
        !           415: 
        !           416:                if ((dp & 0x4) == 0)
        !           417:                        base += regd;
        !           418:                if (dp & 0x3)
        !           419:                        base = get_long (base);
        !           420:                if (dp & 0x4)
        !           421:                        base += regd;
        !           422: 
        !           423:                return base + outer;
        !           424:        } else {
        !           425:                return base + (uae_s32)((uae_s8)dp) + regd;
        !           426:        }
        !           427: }
        !           428: 
        !           429: uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx)
        !           430: {
        !           431:        uae_u16 dp = x_next_iword ();
        !           432:        int reg = (dp >> 12) & 15;
        !           433:        int cycles = 0;
        !           434:        uae_u32 v;
        !           435: 
        !           436:        uae_s32 regd = regs.regs[reg];
        !           437:        if ((dp & 0x800) == 0)
        !           438:                regd = (uae_s32)(uae_s16)regd;
        !           439:        regd <<= (dp >> 9) & 3;
        !           440:        if (dp & 0x100) {
        !           441:                uae_s32 outer = 0;
        !           442:                if (dp & 0x80)
        !           443:                        base = 0;
        !           444:                if (dp & 0x40)
        !           445:                        regd = 0;
        !           446: 
        !           447:                if ((dp & 0x30) == 0x20) {
        !           448:                        base += (uae_s32)(uae_s16) x_next_iword ();
        !           449:                        cycles++;
        !           450:                }
        !           451:                if ((dp & 0x30) == 0x30) {
        !           452:                        base += x_next_ilong ();
        !           453:                        cycles++;
        !           454:                }
        !           455: 
        !           456:                if ((dp & 0x3) == 0x2) {
        !           457:                        outer = (uae_s32)(uae_s16) x_next_iword ();
        !           458:                        cycles++;
        !           459:                }
        !           460:                if ((dp & 0x3) == 0x3) {
        !           461:                        outer = x_next_ilong ();
        !           462:                        cycles++;
        !           463:                }
        !           464: 
        !           465:                if ((dp & 0x4) == 0) {
        !           466:                        base += regd;
        !           467:                        cycles++;
        !           468:                }
        !           469:                if (dp & 0x3) {
        !           470:                        base = x_get_long (base);
        !           471:                        cycles++;
        !           472:                }
        !           473:                if (dp & 0x4) {
        !           474:                        base += regd;
        !           475:                        cycles++;
        !           476:                }
        !           477:                v = base + outer;
        !           478:        } else {
        !           479:                v = base + (uae_s32)((uae_s8)dp) + regd;
        !           480:        }
        !           481: //     if (cycles && currprefs.cpu_cycle_exact)
        !           482: //             x_do_cycles (cycles * cpucycleunit);
        !           483:        return v;
        !           484: }
        !           485: 
        !           486: uae_u32 REGPARAM2 x_get_disp_ea_ce030 (uae_u32 base, int idx)
        !           487: {
        !           488:        uae_u16 dp = next_iword_030ce ();
        !           489:        int reg = (dp >> 12) & 15;
        !           490:        uae_u32 v;
        !           491: 
        !           492:        uae_s32 regd = regs.regs[reg];
        !           493:        if ((dp & 0x800) == 0)
        !           494:                regd = (uae_s32)(uae_s16)regd;
        !           495:        regd <<= (dp >> 9) & 3;
        !           496:        if (dp & 0x100) {
        !           497:                uae_s32 outer = 0;
        !           498:                if (dp & 0x80)
        !           499:                        base = 0;
        !           500:                if (dp & 0x40)
        !           501:                        regd = 0;
        !           502: 
        !           503:                if ((dp & 0x30) == 0x20) {
        !           504:                        base += (uae_s32)(uae_s16) next_iword_030ce ();
        !           505:                }
        !           506:                if ((dp & 0x30) == 0x30) {
        !           507:                        base += next_ilong_030ce ();
        !           508:                }
        !           509: 
        !           510:                if ((dp & 0x3) == 0x2) {
        !           511:                        outer = (uae_s32)(uae_s16) next_iword_030ce ();
        !           512:                }
        !           513:                if ((dp & 0x3) == 0x3) {
        !           514:                        outer = next_ilong_030ce ();
        !           515:                }
        !           516: 
        !           517:                if ((dp & 0x4) == 0) {
        !           518:                        base += regd;
        !           519:                }
        !           520:                if (dp & 0x3) {
        !           521:                        base = x_get_long (base);
        !           522:                }
        !           523:                if (dp & 0x4) {
        !           524:                        base += regd;
        !           525:                }
        !           526:                v = base + outer;
        !           527:        } else {
        !           528:                v = base + (uae_s32)((uae_s8)dp) + regd;
        !           529:        }
        !           530:        return v;
        !           531: }
        !           532: 
        !           533: uae_u32 REGPARAM2 x_get_disp_ea_ce020 (uae_u32 base, int idx)
        !           534: {
        !           535:        uae_u16 dp = next_iword_020ce ();
        !           536:        int reg = (dp >> 12) & 15;
        !           537:        uae_u32 v;
        !           538: 
        !           539:        uae_s32 regd = regs.regs[reg];
        !           540:        if ((dp & 0x800) == 0)
        !           541:                regd = (uae_s32)(uae_s16)regd;
        !           542:        regd <<= (dp >> 9) & 3;
        !           543:        if (dp & 0x100) {
        !           544:                uae_s32 outer = 0;
        !           545:                if (dp & 0x80)
        !           546:                        base = 0;
        !           547:                if (dp & 0x40)
        !           548:                        regd = 0;
        !           549: 
        !           550:                if ((dp & 0x30) == 0x20) {
        !           551:                        base += (uae_s32)(uae_s16) next_iword_020ce ();
        !           552:                }
        !           553:                if ((dp & 0x30) == 0x30) {
        !           554:                        base += next_ilong_020ce ();
        !           555:                }
        !           556: 
        !           557:                if ((dp & 0x3) == 0x2) {
        !           558:                        outer = (uae_s32)(uae_s16) next_iword_020ce ();
        !           559:                }
        !           560:                if ((dp & 0x3) == 0x3) {
        !           561:                        outer = next_ilong_020ce ();
        !           562:                }
        !           563: 
        !           564:                if ((dp & 0x4) == 0) {
        !           565:                        base += regd;
        !           566:                }
        !           567:                if (dp & 0x3) {
        !           568:                        base = x_get_long (base);
        !           569:                }
        !           570:                if (dp & 0x4) {
        !           571:                        base += regd;
        !           572:                }
        !           573:                v = base + outer;
        !           574:        } else {
        !           575:                v = base + (uae_s32)((uae_s8)dp) + regd;
        !           576:        }
        !           577:        return v;
        !           578: }
        !           579: 
        !           580: 
        !           581: /*
        !           582: * Compute exact number of CPU cycles taken
        !           583: * by DIVU and DIVS on a 68000 processor.
        !           584: *
        !           585: * Copyright (c) 2005 by Jorge Cwik, [email protected]
        !           586: *
        !           587: * This is free software; you can redistribute it and/or modify
        !           588: * it under the terms of the GNU General Public License as published by
        !           589: * the Free Software Foundation; either version 2 of the License, or
        !           590: * (at your option) any later version.
        !           591: *
        !           592: * This software is distributed in the hope that it will be useful,
        !           593: * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !           594: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !           595: * GNU General Public License for more details.
        !           596: *
        !           597: * You should have received a copy of the GNU General Public License
        !           598: * along with this software; if not, write to the Free Software
        !           599: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !           600: *
        !           601: */
        !           602: 
        !           603: 
        !           604: /*
        !           605: 
        !           606: The routines below take dividend and divisor as parameters.
        !           607: They return 0 if division by zero, or exact number of cycles otherwise.
        !           608: 
        !           609: The number of cycles returned assumes a register operand.
        !           610: Effective address time must be added if memory operand.
        !           611: 
        !           612: For 68000 only (not 68010, 68012, 68020, etc).
        !           613: Probably valid for 68008 after adding the extra prefetch cycle.
        !           614: 
        !           615: 
        !           616: Best and worst cases for register operand:
        !           617: (Note the difference with the documented range.)
        !           618: 
        !           619: 
        !           620: DIVU:
        !           621: 
        !           622: Overflow (always): 10 cycles.
        !           623: Worst case: 136 cycles.
        !           624: Best case: 76 cycles.
        !           625: 
        !           626: 
        !           627: DIVS:
        !           628: 
        !           629: Absolute overflow: 16-18 cycles.
        !           630: Signed overflow is not detected prematurely.
        !           631: 
        !           632: Worst case: 156 cycles.
        !           633: Best case without signed overflow: 122 cycles.
        !           634: Best case with signed overflow: 120 cycles
        !           635: 
        !           636: 
        !           637: */
        !           638: 
        !           639: int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor)
        !           640: {
        !           641:        int mcycles;
        !           642:        uae_u32 hdivisor;
        !           643:        int i;
        !           644: 
        !           645:        if (divisor == 0)
        !           646:                return 0;
        !           647: 
        !           648:        // Overflow
        !           649:        if ((dividend >> 16) >= divisor)
        !           650:                return (mcycles = 5) * 2;
        !           651: 
        !           652:        mcycles = 38;
        !           653:        hdivisor = divisor << 16;
        !           654: 
        !           655:        for (i = 0; i < 15; i++) {
        !           656:                uae_u32 temp;
        !           657:                temp = dividend;
        !           658: 
        !           659:                dividend <<= 1;
        !           660: 
        !           661:                // If carry from shift
        !           662:                if ((uae_s32)temp < 0)
        !           663:                        dividend -= hdivisor;
        !           664:                else {
        !           665:                        mcycles += 2;
        !           666:                        if (dividend >= hdivisor) {
        !           667:                                dividend -= hdivisor;
        !           668:                                mcycles--;
        !           669:                        }
        !           670:                }
        !           671:        }
        !           672:        return mcycles * 2;
        !           673: }
        !           674: 
        !           675: int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
        !           676: {
        !           677:        int mcycles;
        !           678:        uae_u32 aquot;
        !           679:        int i;
        !           680: 
        !           681:        if (divisor == 0)
        !           682:                return 0;
        !           683: 
        !           684:        mcycles = 6;
        !           685: 
        !           686:        if (dividend < 0)
        !           687:                mcycles++;
        !           688: 
        !           689:        // Check for absolute overflow
        !           690:        if (((uae_u32)abs (dividend) >> 16) >= (uae_u16)abs (divisor))
        !           691:                return (mcycles + 2) * 2;
        !           692: 
        !           693:        // Absolute quotient
        !           694:        aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor);
        !           695: 
        !           696:        mcycles += 55;
        !           697: 
        !           698:        if (divisor >= 0) {
        !           699:                if (dividend >= 0)
        !           700:                        mcycles--;
        !           701:                else
        !           702:                        mcycles++;
        !           703:        }
        !           704: 
        !           705:        // Count 15 msbits in absolute of quotient
        !           706: 
        !           707:        for (i = 0; i < 15; i++) {
        !           708:                if ((uae_s16)aquot >= 0)
        !           709:                        mcycles++;
        !           710:                aquot <<= 1;
        !           711:        }
        !           712: 
        !           713:        return mcycles * 2;
        !           714: }
        !           715: 
        !           716: /* 68000 Z=1. NVC=0
        !           717:  * 68020 and 68030: Signed: Z=1 NVC=0. Unsigned: V=1, N<dst, Z=!N, C=0.
        !           718:  * 68040/68060 C=0.
        !           719:  */
        !           720: void divbyzero_special (bool issigned, uae_s32 dst)
        !           721: {
        !           722:        if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
        !           723:                CLEAR_CZNV ();
        !           724:                if (issigned == false) {
        !           725:                        if (dst < 0) 
        !           726:                                SET_NFLG (1);
        !           727:                        SET_ZFLG (!GET_NFLG ());
        !           728:                        SET_VFLG (1);
        !           729:                } else {
        !           730:                        SET_ZFLG (1);
        !           731:                }
        !           732:        } else if (currprefs.cpu_model >= 68040) {
        !           733:                SET_CFLG (0);
        !           734:        } else {
        !           735:                // 68000/010
        !           736:                CLEAR_CZNV ();
        !           737:        }
        !           738: }
        !           739: 
        !           740: #ifndef CPUEMU_68000_ONLY
        !           741: 
        !           742: STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
        !           743: {
        !           744:        uae_u32 q = 0, cbit = 0;
        !           745:        int i;
        !           746: 
        !           747:        if (div <= src_hi) {
        !           748:                return 1;
        !           749:        }
        !           750:        for (i = 0 ; i < 32 ; i++) {
        !           751:                cbit = src_hi & 0x80000000ul;
        !           752:                src_hi <<= 1;
        !           753:                if (src_lo & 0x80000000ul) src_hi++;
        !           754:                src_lo <<= 1;
        !           755:                q = q << 1;
        !           756:                if (cbit || div <= src_hi) {
        !           757:                        q |= 1;
        !           758:                        src_hi -= div;
        !           759:                }
        !           760:        }
        !           761:        *quot = q;
        !           762:        *rem = src_hi;
        !           763:        return 0;
        !           764: }
        !           765: 
        !           766: bool m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
        !           767: {
        !           768:        if ((extra & 0x400) && currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
        !           769:                op_unimpl (opcode);
        !           770:                return false;
        !           771:        }
        !           772:        if (src == 0) {
        !           773:                Exception (5);
        !           774:                return false;
        !           775:        }
        !           776: #if defined (uae_s64)
        !           777:        if (extra & 0x800) {
        !           778:                /* signed variant */
        !           779:                uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !           780:                uae_s64 quot, rem;
        !           781: 
        !           782:                if (extra & 0x400) {
        !           783:                        a &= 0xffffffffu;
        !           784:                        a |= (uae_s64)m68k_dreg (regs, extra & 7) << 32;
        !           785:                }
        !           786: 
        !           787:                if (a == 0x8000000000000000 && src == -1) {
        !           788:                        SET_VFLG (1);
        !           789:                        SET_NFLG (1);
        !           790:                        SET_CFLG (0);
        !           791:                } else {
        !           792:                        rem = a % (uae_s64)(uae_s32)src;
        !           793:                        quot = a / (uae_s64)(uae_s32)src;
        !           794:                        if ((quot & UVAL64 (0xffffffff80000000)) != 0
        !           795:                                && (quot & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
        !           796:                        {
        !           797:                                SET_VFLG (1);
        !           798:                                SET_NFLG (1);
        !           799:                                SET_CFLG (0);
        !           800:                        } else {
        !           801:                                if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
        !           802:                                SET_VFLG (0);
        !           803:                                SET_CFLG (0);
        !           804:                                SET_ZFLG (((uae_s32)quot) == 0);
        !           805:                                SET_NFLG (((uae_s32)quot) < 0);
        !           806:                                m68k_dreg (regs, extra & 7) = (uae_u32)rem;
        !           807:                                m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
        !           808:                        }
        !           809:                }
        !           810:        } else {
        !           811:                /* unsigned */
        !           812:                uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
        !           813:                uae_u64 quot, rem;
        !           814: 
        !           815:                if (extra & 0x400) {
        !           816:                        a &= 0xffffffffu;
        !           817:                        a |= (uae_u64)m68k_dreg (regs, extra & 7) << 32;
        !           818:                }
        !           819:                rem = a % (uae_u64)src;
        !           820:                quot = a / (uae_u64)src;
        !           821:                if (quot > 0xffffffffu) {
        !           822:                        SET_VFLG (1);
        !           823:                        SET_NFLG (1);
        !           824:                        SET_CFLG (0);
        !           825:                } else {
        !           826:                        SET_VFLG (0);
        !           827:                        SET_CFLG (0);
        !           828:                        SET_ZFLG (((uae_s32)quot) == 0);
        !           829:                        SET_NFLG (((uae_s32)quot) < 0);
        !           830:                        m68k_dreg (regs, extra & 7) = (uae_u32)rem;
        !           831:                        m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
        !           832:                }
        !           833:        }
        !           834: #else
        !           835:        if (extra & 0x800) {
        !           836:                /* signed variant */
        !           837:                uae_s32 lo = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !           838:                uae_s32 hi = lo < 0 ? -1 : 0;
        !           839:                uae_s32 save_high;
        !           840:                uae_u32 quot, rem;
        !           841:                uae_u32 sign;
        !           842: 
        !           843:                if (extra & 0x400) {
        !           844:                        hi = (uae_s32)m68k_dreg (regs, extra & 7);
        !           845:                }
        !           846:                save_high = hi;
        !           847:                sign = (hi ^ src);
        !           848:                if (hi < 0) {
        !           849:                        hi = ~hi;
        !           850:                        lo = -lo;
        !           851:                        if (lo == 0) hi++;
        !           852:                }
        !           853:                if ((uae_s32)src < 0) src = -src;
        !           854:                if (div_unsigned (hi, lo, src, &quot, &rem) ||
        !           855:                        (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
        !           856:                                SET_VFLG (1);
        !           857:                                SET_NFLG (1);
        !           858:                                SET_CFLG (0);
        !           859:                } else {
        !           860:                        if (sign & 0x80000000) quot = -quot;
        !           861:                        if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
        !           862:                        SET_VFLG (0);
        !           863:                        SET_CFLG (0);
        !           864:                        SET_ZFLG (((uae_s32)quot) == 0);
        !           865:                        SET_NFLG (((uae_s32)quot) < 0);
        !           866:                        m68k_dreg (regs, extra & 7) = rem;
        !           867:                        m68k_dreg (regs, (extra >> 12) & 7) = quot;
        !           868:                }
        !           869:        } else {
        !           870:                /* unsigned */
        !           871:                uae_u32 lo = (uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
        !           872:                uae_u32 hi = 0;
        !           873:                uae_u32 quot, rem;
        !           874: 
        !           875:                if (extra & 0x400) {
        !           876:                        hi = (uae_u32)m68k_dreg (regs, extra & 7);
        !           877:                }
        !           878:                if (div_unsigned (hi, lo, src, &quot, &rem)) {
        !           879:                        SET_VFLG (1);
        !           880:                        SET_NFLG (1);
        !           881:                        SET_CFLG (0);
        !           882:                } else {
        !           883:                        SET_VFLG (0);
        !           884:                        SET_CFLG (0);
        !           885:                        SET_ZFLG (((uae_s32)quot) == 0);
        !           886:                        SET_NFLG (((uae_s32)quot) < 0);
        !           887:                        m68k_dreg (regs, extra & 7) = rem;
        !           888:                        m68k_dreg (regs, (extra >> 12) & 7) = quot;
        !           889:                }
        !           890:        }
        !           891: #endif
        !           892:        return true;
        !           893: }
        !           894: 
        !           895: STATIC_INLINE void mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
        !           896: {
        !           897:        uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
        !           898:        uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
        !           899:        uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
        !           900:        uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
        !           901:        uae_u32 lo;
        !           902: 
        !           903:        lo = r0 + ((r1 << 16) & 0xffff0000ul);
        !           904:        if (lo < r0) r3++;
        !           905:        r0 = lo;
        !           906:        lo = r0 + ((r2 << 16) & 0xffff0000ul);
        !           907:        if (lo < r0) r3++;
        !           908:        r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
        !           909:        *dst_lo = lo;
        !           910:        *dst_hi = r3;
        !           911: }
        !           912: 
        !           913: bool m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
        !           914: {
        !           915:        if ((extra & 0x400) && currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
        !           916:                op_unimpl (opcode);
        !           917:                return false;
        !           918:        }
        !           919: #if defined (uae_s64)
        !           920:        if (extra & 0x800) {
        !           921:                /* signed variant */
        !           922:                uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !           923: 
        !           924:                a *= (uae_s64)(uae_s32)src;
        !           925:                SET_VFLG (0);
        !           926:                SET_CFLG (0);
        !           927:                SET_ZFLG (a == 0);
        !           928:                SET_NFLG (a < 0);
        !           929:                if (extra & 0x400)
        !           930:                        m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
        !           931:                else if ((a & UVAL64 (0xffffffff80000000)) != 0
        !           932:                        && (a & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
        !           933:                {
        !           934:                        SET_VFLG (1);
        !           935:                }
        !           936:                m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
        !           937:        } else {
        !           938:                /* unsigned */
        !           939:                uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
        !           940: 
        !           941:                a *= (uae_u64)src;
        !           942:                SET_VFLG (0);
        !           943:                SET_CFLG (0);
        !           944:                SET_ZFLG (a == 0);
        !           945:                SET_NFLG (((uae_s64)a) < 0);
        !           946:                if (extra & 0x400)
        !           947:                        m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
        !           948:                else if ((a & UVAL64 (0xffffffff00000000)) != 0) {
        !           949:                        SET_VFLG (1);
        !           950:                }
        !           951:                m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
        !           952:        }
        !           953: #else
        !           954:        if (extra & 0x800) {
        !           955:                /* signed variant */
        !           956:                uae_s32 src1, src2;
        !           957:                uae_u32 dst_lo, dst_hi;
        !           958:                uae_u32 sign;
        !           959: 
        !           960:                src1 = (uae_s32)src;
        !           961:                src2 = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
        !           962:                sign = (src1 ^ src2);
        !           963:                if (src1 < 0) src1 = -src1;
        !           964:                if (src2 < 0) src2 = -src2;
        !           965:                mul_unsigned ((uae_u32)src1, (uae_u32)src2, &dst_hi, &dst_lo);
        !           966:                if (sign & 0x80000000) {
        !           967:                        dst_hi = ~dst_hi;
        !           968:                        dst_lo = -dst_lo;
        !           969:                        if (dst_lo == 0) dst_hi++;
        !           970:                }
        !           971:                SET_VFLG (0);
        !           972:                SET_CFLG (0);
        !           973:                SET_ZFLG (dst_hi == 0 && dst_lo == 0);
        !           974:                SET_NFLG (((uae_s32)dst_hi) < 0);
        !           975:                if (extra & 0x400)
        !           976:                        m68k_dreg (regs, extra & 7) = dst_hi;
        !           977:                else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
        !           978:                        && ((dst_hi & 0xffffffff) != 0xffffffff
        !           979:                        || (dst_lo & 0x80000000) != 0x80000000))
        !           980:                {
        !           981:                        SET_VFLG (1);
        !           982:                }
        !           983:                m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
        !           984:        } else {
        !           985:                /* unsigned */
        !           986:                uae_u32 dst_lo, dst_hi;
        !           987: 
        !           988:                mul_unsigned (src, (uae_u32)m68k_dreg (regs, (extra >> 12) & 7), &dst_hi, &dst_lo);
        !           989: 
        !           990:                SET_VFLG (0);
        !           991:                SET_CFLG (0);
        !           992:                SET_ZFLG (dst_hi == 0 && dst_lo == 0);
        !           993:                SET_NFLG (((uae_s32)dst_hi) < 0);
        !           994:                if (extra & 0x400)
        !           995:                        m68k_dreg (regs, extra & 7) = dst_hi;
        !           996:                else if (dst_hi != 0) {
        !           997:                        SET_VFLG (1);
        !           998:                }
        !           999:                m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
        !          1000:        }
        !          1001: #endif
        !          1002:        return true;
        !          1003: }
        !          1004: 
        !          1005: #endif

unix.superglobalmegacorp.com

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