Annotation of previous/src/cpu/cpuemu_common.c, revision 1.1.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.