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