|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * MC68881 emulation ! 5: * ! 6: * Copyright 1996 Herman ten Brugge ! 7: */ ! 8: ! 9: #include <math.h> ! 10: ! 11: #include "sysdeps.h" ! 12: #include "hatari-glue.h" ! 13: #include "maccess.h" ! 14: #include "memory.h" ! 15: #include "newcpu.h" ! 16: #include "fpp-unknown.h" ! 17: ! 18: /* ! 19: #include "sysconfig.h" ! 20: #include "config.h" ! 21: #include "options.h" ! 22: #include "custom.h" ! 23: */ ! 24: ! 25: #if 1 ! 26: ! 27: #define DEBUG_FPP 0 ! 28: ! 29: #define MAKE_FPSR(fpsr,r) (fpsr) = ((fpsr) & 0x00FFFFFF) | ((r) == 0 ? 0x4000000 : 0) | ((r) < 0 ? 0x8000000 : 0) ! 30: ! 31: /* single : S 8*E 23*F */ ! 32: /* double : S 11*E 52*F */ ! 33: /* extended : S 15*E 64*F */ ! 34: /* E = 0 & F = 0 -> 0 */ ! 35: /* E = MAX & F = 0 -> Infin */ ! 36: /* E = MAX & F # 0 -> NotANumber */ ! 37: /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */ ! 38: ! 39: STATIC_INLINE double to_pack (uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) ! 40: { ! 41: double d; ! 42: char *cp; ! 43: char str[100]; ! 44: ! 45: cp = str; ! 46: if (wrd1 & 0x80000000) ! 47: *cp++ = '-'; ! 48: *cp++ = (wrd1 & 0xf) + '0'; ! 49: *cp++ = '.'; ! 50: *cp++ = ((wrd2 >> 28) & 0xf) + '0'; ! 51: *cp++ = ((wrd2 >> 24) & 0xf) + '0'; ! 52: *cp++ = ((wrd2 >> 20) & 0xf) + '0'; ! 53: *cp++ = ((wrd2 >> 16) & 0xf) + '0'; ! 54: *cp++ = ((wrd2 >> 12) & 0xf) + '0'; ! 55: *cp++ = ((wrd2 >> 8) & 0xf) + '0'; ! 56: *cp++ = ((wrd2 >> 4) & 0xf) + '0'; ! 57: *cp++ = ((wrd2 >> 0) & 0xf) + '0'; ! 58: *cp++ = ((wrd3 >> 28) & 0xf) + '0'; ! 59: *cp++ = ((wrd3 >> 24) & 0xf) + '0'; ! 60: *cp++ = ((wrd3 >> 20) & 0xf) + '0'; ! 61: *cp++ = ((wrd3 >> 16) & 0xf) + '0'; ! 62: *cp++ = ((wrd3 >> 12) & 0xf) + '0'; ! 63: *cp++ = ((wrd3 >> 8) & 0xf) + '0'; ! 64: *cp++ = ((wrd3 >> 4) & 0xf) + '0'; ! 65: *cp++ = ((wrd3 >> 0) & 0xf) + '0'; ! 66: *cp++ = 'E'; ! 67: if (wrd1 & 0x40000000) ! 68: *cp++ = '-'; ! 69: *cp++ = ((wrd1 >> 24) & 0xf) + '0'; ! 70: *cp++ = ((wrd1 >> 20) & 0xf) + '0'; ! 71: *cp++ = ((wrd1 >> 16) & 0xf) + '0'; ! 72: *cp = 0; ! 73: sscanf (str, "%le", &d); ! 74: return d; ! 75: } ! 76: ! 77: STATIC_INLINE void from_pack (double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) ! 78: { ! 79: int i; ! 80: int t; ! 81: char *cp; ! 82: char str[100]; ! 83: ! 84: sprintf (str, "%.16e", src); ! 85: cp = str; ! 86: *wrd1 = *wrd2 = *wrd3 = 0; ! 87: if (*cp == '-') { ! 88: cp++; ! 89: *wrd1 = 0x80000000; ! 90: } ! 91: if (*cp == '+') ! 92: cp++; ! 93: *wrd1 |= (*cp++ - '0'); ! 94: if (*cp == '.') ! 95: cp++; ! 96: for (i = 0; i < 8; i++) { ! 97: *wrd2 <<= 4; ! 98: if (*cp >= '0' && *cp <= '9') ! 99: *wrd2 |= *cp++ - '0'; ! 100: } ! 101: for (i = 0; i < 8; i++) { ! 102: *wrd3 <<= 4; ! 103: if (*cp >= '0' && *cp <= '9') ! 104: *wrd3 |= *cp++ - '0'; ! 105: } ! 106: if (*cp == 'e' || *cp == 'E') { ! 107: cp++; ! 108: if (*cp == '-') { ! 109: cp++; ! 110: *wrd1 |= 0x40000000; ! 111: } ! 112: if (*cp == '+') ! 113: cp++; ! 114: t = 0; ! 115: for (i = 0; i < 3; i++) { ! 116: if (*cp >= '0' && *cp <= '9') ! 117: t = (t << 4) | (*cp++ - '0'); ! 118: } ! 119: *wrd1 |= t << 16; ! 120: } ! 121: } ! 122: ! 123: STATIC_INLINE int get_fp_value (uae_u32 opcode, uae_u16 extra, double *src) ! 124: { ! 125: uaecptr tmppc; ! 126: uae_u16 tmp; ! 127: int size; ! 128: int mode; ! 129: int reg; ! 130: uae_u32 ad = 0; ! 131: static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; ! 132: static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; ! 133: ! 134: if ((extra & 0x4000) == 0) { ! 135: *src = regs.fp[(extra >> 10) & 7]; ! 136: return 1; ! 137: } ! 138: mode = (opcode >> 3) & 7; ! 139: reg = opcode & 7; ! 140: size = (extra >> 10) & 7; ! 141: switch (mode) { ! 142: case 0: ! 143: switch (size) { ! 144: case 6: ! 145: *src = (double) (uae_s8) m68k_dreg (regs, reg); ! 146: break; ! 147: case 4: ! 148: *src = (double) (uae_s16) m68k_dreg (regs, reg); ! 149: break; ! 150: case 0: ! 151: *src = (double) (uae_s32) m68k_dreg (regs, reg); ! 152: break; ! 153: case 1: ! 154: *src = to_single (m68k_dreg (regs, reg)); ! 155: break; ! 156: default: ! 157: return 0; ! 158: } ! 159: return 1; ! 160: case 1: ! 161: return 0; ! 162: case 2: ! 163: ad = m68k_areg (regs, reg); ! 164: break; ! 165: case 3: ! 166: ad = m68k_areg (regs, reg); ! 167: m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; ! 168: break; ! 169: case 4: ! 170: m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; ! 171: ad = m68k_areg (regs, reg); ! 172: break; ! 173: case 5: ! 174: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword (); ! 175: break; ! 176: case 6: ! 177: ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); ! 178: break; ! 179: case 7: ! 180: switch (reg) { ! 181: case 0: ! 182: ad = (uae_s32) (uae_s16) next_iword (); ! 183: break; ! 184: case 1: ! 185: ad = next_ilong (); ! 186: break; ! 187: case 2: ! 188: ad = m68k_getpc (); ! 189: ad += (uae_s32) (uae_s16) next_iword (); ! 190: break; ! 191: case 3: ! 192: tmppc = m68k_getpc (); ! 193: tmp = next_iword (); ! 194: ad = get_disp_ea_020 (tmppc, tmp); ! 195: break; ! 196: case 4: ! 197: ad = m68k_getpc (); ! 198: m68k_setpc (ad + sz2[size]); ! 199: break; ! 200: default: ! 201: return 0; ! 202: } ! 203: } ! 204: switch (size) { ! 205: case 0: ! 206: *src = (double) (uae_s32) get_long (ad); ! 207: break; ! 208: case 1: ! 209: *src = to_single (get_long (ad)); ! 210: break; ! 211: case 2:{ ! 212: uae_u32 wrd1, wrd2, wrd3; ! 213: wrd1 = get_long (ad); ! 214: ad += 4; ! 215: wrd2 = get_long (ad); ! 216: ad += 4; ! 217: wrd3 = get_long (ad); ! 218: *src = to_exten (wrd1, wrd2, wrd3); ! 219: } ! 220: break; ! 221: case 3:{ ! 222: uae_u32 wrd1, wrd2, wrd3; ! 223: wrd1 = get_long (ad); ! 224: ad += 4; ! 225: wrd2 = get_long (ad); ! 226: ad += 4; ! 227: wrd3 = get_long (ad); ! 228: *src = to_pack (wrd1, wrd2, wrd3); ! 229: } ! 230: break; ! 231: case 4: ! 232: *src = (double) (uae_s16) get_word (ad); ! 233: break; ! 234: case 5:{ ! 235: uae_u32 wrd1, wrd2; ! 236: wrd1 = get_long (ad); ! 237: ad += 4; ! 238: wrd2 = get_long (ad); ! 239: *src = to_double (wrd1, wrd2); ! 240: } ! 241: break; ! 242: case 6: ! 243: *src = (double) (uae_s8) get_byte (ad); ! 244: break; ! 245: default: ! 246: return 0; ! 247: } ! 248: return 1; ! 249: } ! 250: ! 251: STATIC_INLINE int put_fp_value (double value, uae_u32 opcode, uae_u16 extra) ! 252: { ! 253: uae_u16 tmp; ! 254: uaecptr tmppc; ! 255: int size; ! 256: int mode; ! 257: int reg; ! 258: uae_u32 ad; ! 259: static int sz1[8] = { 4, 4, 12, 12, 2, 8, 1, 0 }; ! 260: static int sz2[8] = { 4, 4, 12, 12, 2, 8, 2, 0 }; ! 261: ! 262: if ((extra & 0x4000) == 0) { ! 263: regs.fp[(extra >> 10) & 7] = value; ! 264: return 1; ! 265: } ! 266: mode = (opcode >> 3) & 7; ! 267: reg = opcode & 7; ! 268: size = (extra >> 10) & 7; ! 269: ad = -1; ! 270: switch (mode) { ! 271: case 0: ! 272: switch (size) { ! 273: case 6: ! 274: m68k_dreg (regs, reg) = (((int) value & 0xff) ! 275: | (m68k_dreg (regs, reg) & ~0xff)); ! 276: break; ! 277: case 4: ! 278: m68k_dreg (regs, reg) = (((int) value & 0xffff) ! 279: | (m68k_dreg (regs, reg) & ~0xffff)); ! 280: break; ! 281: case 0: ! 282: m68k_dreg (regs, reg) = (int) value; ! 283: break; ! 284: case 1: ! 285: m68k_dreg (regs, reg) = from_single (value); ! 286: break; ! 287: default: ! 288: return 0; ! 289: } ! 290: return 1; ! 291: case 1: ! 292: return 0; ! 293: case 2: ! 294: ad = m68k_areg (regs, reg); ! 295: break; ! 296: case 3: ! 297: ad = m68k_areg (regs, reg); ! 298: m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size]; ! 299: break; ! 300: case 4: ! 301: m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size]; ! 302: ad = m68k_areg (regs, reg); ! 303: break; ! 304: case 5: ! 305: ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword (); ! 306: break; ! 307: case 6: ! 308: ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); ! 309: break; ! 310: case 7: ! 311: switch (reg) { ! 312: case 0: ! 313: ad = (uae_s32) (uae_s16) next_iword (); ! 314: break; ! 315: case 1: ! 316: ad = next_ilong (); ! 317: break; ! 318: case 2: ! 319: ad = m68k_getpc (); ! 320: ad += (uae_s32) (uae_s16) next_iword (); ! 321: break; ! 322: case 3: ! 323: tmppc = m68k_getpc (); ! 324: tmp = next_iword (); ! 325: ad = get_disp_ea_020 (tmppc, tmp); ! 326: break; ! 327: case 4: ! 328: ad = m68k_getpc (); ! 329: m68k_setpc (ad + sz2[size]); ! 330: break; ! 331: default: ! 332: return 0; ! 333: } ! 334: } ! 335: switch (size) { ! 336: case 0: ! 337: put_long (ad, (uae_s32) value); ! 338: break; ! 339: case 1: ! 340: put_long (ad, from_single (value)); ! 341: break; ! 342: case 2: ! 343: { ! 344: uae_u32 wrd1, wrd2, wrd3; ! 345: from_exten (value, &wrd1, &wrd2, &wrd3); ! 346: put_long (ad, wrd1); ! 347: ad += 4; ! 348: put_long (ad, wrd2); ! 349: ad += 4; ! 350: put_long (ad, wrd3); ! 351: } ! 352: break; ! 353: case 3: ! 354: { ! 355: uae_u32 wrd1, wrd2, wrd3; ! 356: from_pack (value, &wrd1, &wrd2, &wrd3); ! 357: put_long (ad, wrd1); ! 358: ad += 4; ! 359: put_long (ad, wrd2); ! 360: ad += 4; ! 361: put_long (ad, wrd3); ! 362: } ! 363: break; ! 364: case 4: ! 365: put_word (ad, (uae_s16) value); ! 366: break; ! 367: case 5:{ ! 368: uae_u32 wrd1, wrd2; ! 369: from_double (value, &wrd1, &wrd2); ! 370: put_long (ad, wrd1); ! 371: ad += 4; ! 372: put_long (ad, wrd2); ! 373: } ! 374: break; ! 375: case 6: ! 376: put_byte (ad, (uae_s8) value); ! 377: break; ! 378: default: ! 379: return 0; ! 380: } ! 381: return 1; ! 382: } ! 383: ! 384: STATIC_INLINE int get_fp_ad (uae_u32 opcode, uae_u32 * ad) ! 385: { ! 386: uae_u16 tmp; ! 387: uaecptr tmppc; ! 388: int mode; ! 389: int reg; ! 390: ! 391: mode = (opcode >> 3) & 7; ! 392: reg = opcode & 7; ! 393: switch (mode) { ! 394: case 0: ! 395: case 1: ! 396: return 0; ! 397: case 2: ! 398: *ad = m68k_areg (regs, reg); ! 399: break; ! 400: case 3: ! 401: *ad = m68k_areg (regs, reg); ! 402: break; ! 403: case 4: ! 404: *ad = m68k_areg (regs, reg); ! 405: break; ! 406: case 5: ! 407: *ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword (); ! 408: break; ! 409: case 6: ! 410: *ad = get_disp_ea_020 (m68k_areg (regs, reg), next_iword ()); ! 411: break; ! 412: case 7: ! 413: switch (reg) { ! 414: case 0: ! 415: *ad = (uae_s32) (uae_s16) next_iword (); ! 416: break; ! 417: case 1: ! 418: *ad = next_ilong (); ! 419: break; ! 420: case 2: ! 421: *ad = m68k_getpc (); ! 422: *ad += (uae_s32) (uae_s16) next_iword (); ! 423: break; ! 424: case 3: ! 425: tmppc = m68k_getpc (); ! 426: tmp = next_iword (); ! 427: *ad = get_disp_ea_020 (tmppc, tmp); ! 428: break; ! 429: default: ! 430: return 0; ! 431: } ! 432: } ! 433: return 1; ! 434: } ! 435: ! 436: STATIC_INLINE int fpp_cond (uae_u32 opcode, int contition) ! 437: { ! 438: int N = (regs.fpsr & 0x8000000) != 0; ! 439: int Z = (regs.fpsr & 0x4000000) != 0; ! 440: /* int I = (regs.fpsr & 0x2000000) != 0; */ ! 441: int NotANumber = (regs.fpsr & 0x1000000) != 0; ! 442: ! 443: switch (contition) { ! 444: case 0x00: ! 445: return 0; ! 446: case 0x01: ! 447: return Z; ! 448: case 0x02: ! 449: return !(NotANumber || Z || N); ! 450: case 0x03: ! 451: return Z || !(NotANumber || N); ! 452: case 0x04: ! 453: return N && !(NotANumber || Z); ! 454: case 0x05: ! 455: return Z || (N && !NotANumber); ! 456: case 0x06: ! 457: return !(NotANumber || Z); ! 458: case 0x07: ! 459: return !NotANumber; ! 460: case 0x08: ! 461: return NotANumber; ! 462: case 0x09: ! 463: return NotANumber || Z; ! 464: case 0x0a: ! 465: return NotANumber || !(N || Z); ! 466: case 0x0b: ! 467: return NotANumber || Z || !N; ! 468: case 0x0c: ! 469: return NotANumber || (N && !Z); ! 470: case 0x0d: ! 471: return NotANumber || Z || N; ! 472: case 0x0e: ! 473: return !Z; ! 474: case 0x0f: ! 475: return 1; ! 476: case 0x10: ! 477: return 0; ! 478: case 0x11: ! 479: return Z; ! 480: case 0x12: ! 481: return !(NotANumber || Z || N); ! 482: case 0x13: ! 483: return Z || !(NotANumber || N); ! 484: case 0x14: ! 485: return N && !(NotANumber || Z); ! 486: case 0x15: ! 487: return Z || (N && !NotANumber); ! 488: case 0x16: ! 489: return !(NotANumber || Z); ! 490: case 0x17: ! 491: return !NotANumber; ! 492: case 0x18: ! 493: return NotANumber; ! 494: case 0x19: ! 495: return NotANumber || Z; ! 496: case 0x1a: ! 497: return NotANumber || !(N || Z); ! 498: case 0x1b: ! 499: return NotANumber || Z || !N; ! 500: case 0x1c: ! 501: return NotANumber || (Z && N); ! 502: case 0x1d: ! 503: return NotANumber || Z || N; ! 504: case 0x1e: ! 505: return !Z; ! 506: case 0x1f: ! 507: return 1; ! 508: } ! 509: return -1; ! 510: } ! 511: ! 512: void fdbcc_opp (uae_u32 opcode, uae_u16 extra) ! 513: { ! 514: uaecptr pc = (uae_u32) m68k_getpc (); ! 515: uae_s32 disp = (uae_s32) (uae_s16) next_iword (); ! 516: int cc; ! 517: ! 518: #if DEBUG_FPP ! 519: printf ("fdbcc_opp at %08lx\n", m68k_getpc ()); ! 520: fflush (stdout); ! 521: #endif ! 522: cc = fpp_cond (opcode, extra & 0x3f); ! 523: if (cc == -1) { ! 524: m68k_setpc (pc - 4); ! 525: op_illg (opcode); ! 526: } else if (!cc) { ! 527: int reg = opcode & 0x7; ! 528: ! 529: m68k_dreg (regs, reg) = ((m68k_dreg (regs, reg) & ~0xffff) ! 530: | ((m68k_dreg (regs, reg) - 1) & 0xffff)); ! 531: if ((m68k_dreg (regs, reg) & 0xffff) == 0xffff) ! 532: m68k_setpc (pc + disp); ! 533: } ! 534: } ! 535: ! 536: void fscc_opp (uae_u32 opcode, uae_u16 extra) ! 537: { ! 538: uae_u32 ad; ! 539: int cc; ! 540: ! 541: #if DEBUG_FPP ! 542: printf ("fscc_opp at %08lx\n", m68k_getpc ()); ! 543: fflush (stdout); ! 544: #endif ! 545: cc = fpp_cond (opcode, extra & 0x3f); ! 546: if (cc == -1) { ! 547: m68k_setpc (m68k_getpc () - 4); ! 548: op_illg (opcode); ! 549: } else if ((opcode & 0x38) == 0) { ! 550: m68k_dreg (regs, opcode & 7) = (m68k_dreg (regs, opcode & 7) & ~0xff) | (cc ? 0xff : 0x00); ! 551: } else { ! 552: if (get_fp_ad (opcode, &ad) == 0) { ! 553: m68k_setpc (m68k_getpc () - 4); ! 554: op_illg (opcode); ! 555: } else ! 556: put_byte (ad, cc ? 0xff : 0x00); ! 557: } ! 558: } ! 559: ! 560: void ftrapcc_opp (uae_u32 opcode, uaecptr oldpc) ! 561: { ! 562: int cc; ! 563: ! 564: #if DEBUG_FPP ! 565: printf ("ftrapcc_opp at %08lx\n", m68k_getpc ()); ! 566: fflush (stdout); ! 567: #endif ! 568: cc = fpp_cond (opcode, opcode & 0x3f); ! 569: if (cc == -1) { ! 570: m68k_setpc (oldpc); ! 571: op_illg (opcode); ! 572: } ! 573: if (cc) ! 574: Exception (7, oldpc - 2); ! 575: } ! 576: ! 577: void fbcc_opp (uae_u32 opcode, uaecptr pc, uae_u32 extra) ! 578: { ! 579: int cc; ! 580: ! 581: #if DEBUG_FPP ! 582: printf ("fbcc_opp at %08lx\n", m68k_getpc ()); ! 583: fflush (stdout); ! 584: #endif ! 585: cc = fpp_cond (opcode, opcode & 0x3f); ! 586: if (cc == -1) { ! 587: m68k_setpc (pc); ! 588: op_illg (opcode); ! 589: } else if (cc) { ! 590: if ((opcode & 0x40) == 0) ! 591: extra = (uae_s32) (uae_s16) extra; ! 592: m68k_setpc (pc + extra); ! 593: } ! 594: } ! 595: ! 596: void fsave_opp (uae_u32 opcode) ! 597: { ! 598: uae_u32 ad; ! 599: int incr = (opcode & 0x38) == 0x20 ? -1 : 1; ! 600: int i; ! 601: ! 602: #if DEBUG_FPP ! 603: printf ("fsave_opp at %08lx\n", m68k_getpc ()); ! 604: fflush (stdout); ! 605: #endif ! 606: if (get_fp_ad (opcode, &ad) == 0) { ! 607: m68k_setpc (m68k_getpc () - 2); ! 608: op_illg (opcode); ! 609: return; ! 610: } ! 611: ! 612: if (cpu_level == 4) { ! 613: /* 4 byte 68040 IDLE frame. */ ! 614: if (incr < 0) { ! 615: ad -= 4; ! 616: put_long (ad, 0x41000000); ! 617: } else { ! 618: put_long (ad, 0x41000000); ! 619: ad += 4; ! 620: } ! 621: } else { ! 622: if (incr < 0) { ! 623: ad -= 4; ! 624: put_long (ad, 0x70000000); ! 625: for (i = 0; i < 5; i++) { ! 626: ad -= 4; ! 627: put_long (ad, 0x00000000); ! 628: } ! 629: ad -= 4; ! 630: put_long (ad, 0x1f180000); ! 631: } else { ! 632: put_long (ad, 0x1f180000); ! 633: ad += 4; ! 634: for (i = 0; i < 5; i++) { ! 635: put_long (ad, 0x00000000); ! 636: ad += 4; ! 637: } ! 638: put_long (ad, 0x70000000); ! 639: ad += 4; ! 640: } ! 641: } ! 642: if ((opcode & 0x38) == 0x18) ! 643: m68k_areg (regs, opcode & 7) = ad; ! 644: if ((opcode & 0x38) == 0x20) ! 645: m68k_areg (regs, opcode & 7) = ad; ! 646: } ! 647: ! 648: void frestore_opp (uae_u32 opcode) ! 649: { ! 650: uae_u32 ad; ! 651: uae_u32 d; ! 652: int incr = (opcode & 0x38) == 0x20 ? -1 : 1; ! 653: ! 654: #if DEBUG_FPP ! 655: printf ("frestore_opp at %08lx\n", m68k_getpc ()); ! 656: fflush (stdout); ! 657: #endif ! 658: if (get_fp_ad (opcode, &ad) == 0) { ! 659: m68k_setpc (m68k_getpc () - 2); ! 660: op_illg (opcode); ! 661: return; ! 662: } ! 663: if (cpu_level == 4) { ! 664: /* 68040 */ ! 665: if (incr < 0) { ! 666: /* @@@ This may be wrong. */ ! 667: ad -= 4; ! 668: d = get_long (ad); ! 669: if ((d & 0xff000000) != 0) { /* Not a NULL frame? */ ! 670: if ((d & 0x00ff0000) == 0) { /* IDLE */ ! 671: } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */ ! 672: ad -= 44; ! 673: } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */ ! 674: ad -= 92; ! 675: } ! 676: } ! 677: } else { ! 678: d = get_long (ad); ! 679: ad += 4; ! 680: if ((d & 0xff000000) != 0) { /* Not a NULL frame? */ ! 681: if ((d & 0x00ff0000) == 0) { /* IDLE */ ! 682: } else if ((d & 0x00ff0000) == 0x00300000) { /* UNIMP */ ! 683: ad += 44; ! 684: } else if ((d & 0x00ff0000) == 0x00600000) { /* BUSY */ ! 685: ad += 92; ! 686: } ! 687: } ! 688: } ! 689: } else { ! 690: if (incr < 0) { ! 691: ad -= 4; ! 692: d = get_long (ad); ! 693: if ((d & 0xff000000) != 0) { ! 694: if ((d & 0x00ff0000) == 0x00180000) ! 695: ad -= 6 * 4; ! 696: else if ((d & 0x00ff0000) == 0x00380000) ! 697: ad -= 14 * 4; ! 698: else if ((d & 0x00ff0000) == 0x00b40000) ! 699: ad -= 45 * 4; ! 700: } ! 701: } else { ! 702: d = get_long (ad); ! 703: ad += 4; ! 704: if ((d & 0xff000000) != 0) { ! 705: if ((d & 0x00ff0000) == 0x00180000) ! 706: ad += 6 * 4; ! 707: else if ((d & 0x00ff0000) == 0x00380000) ! 708: ad += 14 * 4; ! 709: else if ((d & 0x00ff0000) == 0x00b40000) ! 710: ad += 45 * 4; ! 711: } ! 712: } ! 713: } ! 714: if ((opcode & 0x38) == 0x18) ! 715: m68k_areg (regs, opcode & 7) = ad; ! 716: if ((opcode & 0x38) == 0x20) ! 717: m68k_areg (regs, opcode & 7) = ad; ! 718: } ! 719: ! 720: void fpp_opp (uae_u32 opcode, uae_u16 extra) ! 721: { ! 722: int reg; ! 723: double src; ! 724: ! 725: #if DEBUG_FPP ! 726: printf ("FPP %04lx %04x at %08lx\n", opcode & 0xffff, extra & 0xffff, m68k_getpc () - 4); ! 727: fflush (stdout); ! 728: #endif ! 729: switch ((extra >> 13) & 0x7) { ! 730: case 3: ! 731: if (put_fp_value (regs.fp[(extra >> 7) & 7], opcode, extra) == 0) { ! 732: m68k_setpc (m68k_getpc () - 4); ! 733: op_illg (opcode); ! 734: } ! 735: return; ! 736: case 4: ! 737: case 5: ! 738: if ((opcode & 0x38) == 0) { ! 739: if (extra & 0x2000) { ! 740: if (extra & 0x1000) ! 741: m68k_dreg (regs, opcode & 7) = regs.fpcr; ! 742: if (extra & 0x0800) ! 743: m68k_dreg (regs, opcode & 7) = regs.fpsr; ! 744: if (extra & 0x0400) ! 745: m68k_dreg (regs, opcode & 7) = regs.fpiar; ! 746: } else { ! 747: if (extra & 0x1000) ! 748: regs.fpcr = m68k_dreg (regs, opcode & 7); ! 749: if (extra & 0x0800) ! 750: regs.fpsr = m68k_dreg (regs, opcode & 7); ! 751: if (extra & 0x0400) ! 752: regs.fpiar = m68k_dreg (regs, opcode & 7); ! 753: } ! 754: } else if ((opcode & 0x38) == 1) { ! 755: if (extra & 0x2000) { ! 756: if (extra & 0x1000) ! 757: m68k_areg (regs, opcode & 7) = regs.fpcr; ! 758: if (extra & 0x0800) ! 759: m68k_areg (regs, opcode & 7) = regs.fpsr; ! 760: if (extra & 0x0400) ! 761: m68k_areg (regs, opcode & 7) = regs.fpiar; ! 762: } else { ! 763: if (extra & 0x1000) ! 764: regs.fpcr = m68k_areg (regs, opcode & 7); ! 765: if (extra & 0x0800) ! 766: regs.fpsr = m68k_areg (regs, opcode & 7); ! 767: if (extra & 0x0400) ! 768: regs.fpiar = m68k_areg (regs, opcode & 7); ! 769: } ! 770: } else if ((opcode & 0x3f) == 0x3c) { ! 771: if ((extra & 0x2000) == 0) { ! 772: if (extra & 0x1000) ! 773: regs.fpcr = next_ilong (); ! 774: if (extra & 0x0800) ! 775: regs.fpsr = next_ilong (); ! 776: if (extra & 0x0400) ! 777: regs.fpiar = next_ilong (); ! 778: } ! 779: } else if (extra & 0x2000) { ! 780: /* FMOVEM FPP->memory */ ! 781: uae_u32 ad; ! 782: int incr = 0; ! 783: ! 784: if (get_fp_ad (opcode, &ad) == 0) { ! 785: m68k_setpc (m68k_getpc () - 4); ! 786: op_illg (opcode); ! 787: return; ! 788: } ! 789: if ((opcode & 0x38) == 0x20) { ! 790: if (extra & 0x1000) ! 791: incr += 4; ! 792: if (extra & 0x0800) ! 793: incr += 4; ! 794: if (extra & 0x0400) ! 795: incr += 4; ! 796: } ! 797: ad -= incr; ! 798: if (extra & 0x1000) { ! 799: put_long (ad, regs.fpcr); ! 800: ad += 4; ! 801: } ! 802: if (extra & 0x0800) { ! 803: put_long (ad, regs.fpsr); ! 804: ad += 4; ! 805: } ! 806: if (extra & 0x0400) { ! 807: put_long (ad, regs.fpiar); ! 808: ad += 4; ! 809: } ! 810: ad -= incr; ! 811: if ((opcode & 0x38) == 0x18) ! 812: m68k_areg (regs, opcode & 7) = ad; ! 813: if ((opcode & 0x38) == 0x20) ! 814: m68k_areg (regs, opcode & 7) = ad; ! 815: } else { ! 816: /* FMOVEM memory->FPP */ ! 817: uae_u32 ad; ! 818: ! 819: if (get_fp_ad (opcode, &ad) == 0) { ! 820: m68k_setpc (m68k_getpc () - 4); ! 821: op_illg (opcode); ! 822: return; ! 823: } ! 824: ad = (opcode & 0x38) == 0x20 ? ad - 12 : ad; ! 825: if (extra & 0x1000) { ! 826: regs.fpcr = get_long (ad); ! 827: ad += 4; ! 828: } ! 829: if (extra & 0x0800) { ! 830: regs.fpsr = get_long (ad); ! 831: ad += 4; ! 832: } ! 833: if (extra & 0x0400) { ! 834: regs.fpiar = get_long (ad); ! 835: ad += 4; ! 836: } ! 837: if ((opcode & 0x38) == 0x18) ! 838: m68k_areg (regs, opcode & 7) = ad; ! 839: if ((opcode & 0x38) == 0x20) ! 840: m68k_areg (regs, opcode & 7) = ad - 12; ! 841: } ! 842: return; ! 843: case 6: ! 844: case 7: ! 845: { ! 846: uae_u32 ad, list = 0; ! 847: int incr = 0; ! 848: if (extra & 0x2000) { ! 849: /* FMOVEM FPP->memory */ ! 850: if (get_fp_ad (opcode, &ad) == 0) { ! 851: m68k_setpc (m68k_getpc () - 4); ! 852: op_illg (opcode); ! 853: return; ! 854: } ! 855: switch ((extra >> 11) & 3) { ! 856: case 0: /* static pred */ ! 857: list = extra & 0xff; ! 858: incr = -1; ! 859: break; ! 860: case 1: /* dynamic pred */ ! 861: list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; ! 862: incr = -1; ! 863: break; ! 864: case 2: /* static postinc */ ! 865: list = extra & 0xff; ! 866: incr = 1; ! 867: break; ! 868: case 3: /* dynamic postinc */ ! 869: list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; ! 870: incr = 1; ! 871: break; ! 872: } ! 873: while (list) { ! 874: uae_u32 wrd1, wrd2, wrd3; ! 875: if (incr < 0) { ! 876: from_exten (regs.fp[fpp_movem_index2[list]], &wrd1, &wrd2, &wrd3); ! 877: ad -= 4; ! 878: put_long (ad, wrd3); ! 879: ad -= 4; ! 880: put_long (ad, wrd2); ! 881: ad -= 4; ! 882: put_long (ad, wrd1); ! 883: } else { ! 884: from_exten (regs.fp[fpp_movem_index1[list]], &wrd1, &wrd2, &wrd3); ! 885: put_long (ad, wrd1); ! 886: ad += 4; ! 887: put_long (ad, wrd2); ! 888: ad += 4; ! 889: put_long (ad, wrd3); ! 890: ad += 4; ! 891: } ! 892: list = fpp_movem_next[list]; ! 893: } ! 894: if ((opcode & 0x38) == 0x18) ! 895: m68k_areg (regs, opcode & 7) = ad; ! 896: if ((opcode & 0x38) == 0x20) ! 897: m68k_areg (regs, opcode & 7) = ad; ! 898: } else { ! 899: /* FMOVEM memory->FPP */ ! 900: if (get_fp_ad (opcode, &ad) == 0) { ! 901: m68k_setpc (m68k_getpc () - 4); ! 902: op_illg (opcode); ! 903: return; ! 904: } ! 905: switch ((extra >> 11) & 3) { ! 906: case 0: /* static pred */ ! 907: list = extra & 0xff; ! 908: incr = -1; ! 909: break; ! 910: case 1: /* dynamic pred */ ! 911: list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; ! 912: incr = -1; ! 913: break; ! 914: case 2: /* static postinc */ ! 915: list = extra & 0xff; ! 916: incr = 1; ! 917: break; ! 918: case 3: /* dynamic postinc */ ! 919: list = m68k_dreg (regs, (extra >> 4) & 3) & 0xff; ! 920: incr = 1; ! 921: break; ! 922: } ! 923: while (list) { ! 924: uae_u32 wrd1, wrd2, wrd3; ! 925: if (incr < 0) { ! 926: ad -= 4; ! 927: wrd3 = get_long (ad); ! 928: ad -= 4; ! 929: wrd2 = get_long (ad); ! 930: ad -= 4; ! 931: wrd1 = get_long (ad); ! 932: regs.fp[fpp_movem_index2[list]] = to_exten (wrd1, wrd2, wrd3); ! 933: } else { ! 934: wrd1 = get_long (ad); ! 935: ad += 4; ! 936: wrd2 = get_long (ad); ! 937: ad += 4; ! 938: wrd3 = get_long (ad); ! 939: ad += 4; ! 940: regs.fp[fpp_movem_index1[list]] = to_exten (wrd1, wrd2, wrd3); ! 941: } ! 942: list = fpp_movem_next[list]; ! 943: } ! 944: if ((opcode & 0x38) == 0x18) ! 945: m68k_areg (regs, opcode & 7) = ad; ! 946: if ((opcode & 0x38) == 0x20) ! 947: m68k_areg (regs, opcode & 7) = ad; ! 948: } ! 949: } ! 950: return; ! 951: case 0: ! 952: case 2: ! 953: reg = (extra >> 7) & 7; ! 954: if ((extra & 0xfc00) == 0x5c00) { ! 955: switch (extra & 0x7f) { ! 956: case 0x00: ! 957: regs.fp[reg] = 4.0 * atan (1.0); ! 958: break; ! 959: case 0x0b: ! 960: regs.fp[reg] = log10 (2.0); ! 961: break; ! 962: case 0x0c: ! 963: regs.fp[reg] = exp (1.0); ! 964: break; ! 965: case 0x0d: ! 966: regs.fp[reg] = log (exp (1.0)) / log (2.0); ! 967: break; ! 968: case 0x0e: ! 969: regs.fp[reg] = log (exp (1.0)) / log (10.0); ! 970: break; ! 971: case 0x0f: ! 972: regs.fp[reg] = 0.0; ! 973: break; ! 974: case 0x30: ! 975: regs.fp[reg] = log (2.0); ! 976: break; ! 977: case 0x31: ! 978: regs.fp[reg] = log (10.0); ! 979: break; ! 980: case 0x32: ! 981: regs.fp[reg] = 1.0e0; ! 982: break; ! 983: case 0x33: ! 984: regs.fp[reg] = 1.0e1; ! 985: break; ! 986: case 0x34: ! 987: regs.fp[reg] = 1.0e2; ! 988: break; ! 989: case 0x35: ! 990: regs.fp[reg] = 1.0e4; ! 991: break; ! 992: case 0x36: ! 993: regs.fp[reg] = 1.0e8; ! 994: break; ! 995: case 0x37: ! 996: regs.fp[reg] = 1.0e16; ! 997: break; ! 998: case 0x38: ! 999: regs.fp[reg] = 1.0e32; ! 1000: break; ! 1001: case 0x39: ! 1002: regs.fp[reg] = 1.0e64; ! 1003: break; ! 1004: case 0x3a: ! 1005: regs.fp[reg] = 1.0e128; ! 1006: break; ! 1007: case 0x3b: ! 1008: regs.fp[reg] = 1.0e256; ! 1009: break; ! 1010: #if 0 ! 1011: case 0x3c: ! 1012: regs.fp[reg] = 1.0e512; ! 1013: break; ! 1014: case 0x3d: ! 1015: regs.fp[reg] = 1.0e1024; ! 1016: break; ! 1017: case 0x3e: ! 1018: regs.fp[reg] = 1.0e2048; ! 1019: break; ! 1020: case 0x3f: ! 1021: regs.fp[reg] = 1.0e4096; ! 1022: break; ! 1023: #endif ! 1024: default: ! 1025: m68k_setpc (m68k_getpc () - 4); ! 1026: op_illg (opcode); ! 1027: break; ! 1028: } ! 1029: return; ! 1030: } ! 1031: if (get_fp_value (opcode, extra, &src) == 0) { ! 1032: m68k_setpc (m68k_getpc () - 4); ! 1033: op_illg (opcode); ! 1034: return; ! 1035: } ! 1036: switch (extra & 0x7f) { ! 1037: case 0x00: /* FMOVE */ ! 1038: regs.fp[reg] = src; ! 1039: /* Brian King was here. <ea> to register needs FPSR updated. ! 1040: * See page 3-73 in Motorola 68K programmers reference manual. ! 1041: * %%%FPU */ ! 1042: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1043: break; ! 1044: case 0x01: /* FINT */ ! 1045: /* need to take the current rounding mode into account */ ! 1046: switch ((regs.fpcr >> 4) & 0x3) { ! 1047: case 0: ! 1048: regs.fp[reg] = (int) (src + 0.5); ! 1049: break; ! 1050: case 1: ! 1051: regs.fp[reg] = (int) src; ! 1052: break; ! 1053: case 2: ! 1054: regs.fp[reg] = floor (src); ! 1055: break; ! 1056: case 3: ! 1057: regs.fp[reg] = ceil (src); ! 1058: break; ! 1059: } ! 1060: break; ! 1061: case 0x02: /* FSINH */ ! 1062: regs.fp[reg] = sinh (src); ! 1063: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1064: break; ! 1065: case 0x03: /* FINTRZ */ ! 1066: regs.fp[reg] = (int) src; ! 1067: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1068: break; ! 1069: case 0x04: /* FSQRT */ ! 1070: regs.fp[reg] = sqrt (src); ! 1071: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1072: break; ! 1073: case 0x06: /* FLOGNP1 */ ! 1074: regs.fp[reg] = log (src + 1.0); ! 1075: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1076: break; ! 1077: case 0x08: /* FETOXM1 */ ! 1078: regs.fp[reg] = exp (src) - 1.0; ! 1079: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1080: break; ! 1081: case 0x09: /* FTANH */ ! 1082: regs.fp[reg] = tanh (src); ! 1083: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1084: break; ! 1085: case 0x0a: /* FATAN */ ! 1086: regs.fp[reg] = atan (src); ! 1087: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1088: break; ! 1089: case 0x0c: /* FASIN */ ! 1090: regs.fp[reg] = asin (src); ! 1091: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1092: break; ! 1093: case 0x0d: /* FATANH */ ! 1094: #if 1 /* The BeBox doesn't have atanh, and it isn't in the HPUX libm either */ ! 1095: regs.fp[reg] = log ((1 + src) / (1 - src)) / 2; ! 1096: #else ! 1097: regs.fp[reg] = atanh (src); ! 1098: #endif ! 1099: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1100: break; ! 1101: case 0x0e: /* FSIN */ ! 1102: regs.fp[reg] = sin (src); ! 1103: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1104: break; ! 1105: case 0x0f: /* FTAN */ ! 1106: regs.fp[reg] = tan (src); ! 1107: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1108: break; ! 1109: case 0x10: /* FETOX */ ! 1110: regs.fp[reg] = exp (src); ! 1111: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1112: break; ! 1113: case 0x11: /* FTWOTOX */ ! 1114: regs.fp[reg] = pow (2.0, src); ! 1115: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1116: break; ! 1117: case 0x12: /* FTENTOX */ ! 1118: regs.fp[reg] = pow (10.0, src); ! 1119: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1120: break; ! 1121: case 0x14: /* FLOGN */ ! 1122: regs.fp[reg] = log (src); ! 1123: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1124: break; ! 1125: case 0x15: /* FLOG10 */ ! 1126: regs.fp[reg] = log10 (src); ! 1127: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1128: break; ! 1129: case 0x16: /* FLOG2 */ ! 1130: regs.fp[reg] = log (src) / log (2.0); ! 1131: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1132: break; ! 1133: case 0x18: /* FABS */ ! 1134: regs.fp[reg] = src < 0 ? -src : src; ! 1135: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1136: break; ! 1137: case 0x19: /* FCOSH */ ! 1138: regs.fp[reg] = cosh (src); ! 1139: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1140: break; ! 1141: case 0x1a: /* FNEG */ ! 1142: regs.fp[reg] = -src; ! 1143: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1144: break; ! 1145: case 0x1c: /* FACOS */ ! 1146: regs.fp[reg] = acos (src); ! 1147: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1148: break; ! 1149: case 0x1d: /* FCOS */ ! 1150: regs.fp[reg] = cos (src); ! 1151: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1152: break; ! 1153: case 0x1e: /* FGETEXP */ ! 1154: { ! 1155: int expon; ! 1156: frexp (src, &expon); ! 1157: regs.fp[reg] = (double) (expon - 1); ! 1158: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1159: } ! 1160: break; ! 1161: case 0x1f: /* FGETMAN */ ! 1162: { ! 1163: int expon; ! 1164: regs.fp[reg] = frexp (src, &expon) * 2.0; ! 1165: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1166: } ! 1167: break; ! 1168: case 0x20: /* FDIV */ ! 1169: regs.fp[reg] /= src; ! 1170: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1171: break; ! 1172: case 0x21: /* FMOD */ ! 1173: regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src)) * src; ! 1174: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1175: break; ! 1176: case 0x22: /* FADD */ ! 1177: regs.fp[reg] += src; ! 1178: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1179: break; ! 1180: case 0x23: /* FMUL */ ! 1181: regs.fp[reg] *= src; ! 1182: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1183: break; ! 1184: case 0x24: /* FSGLDIV */ ! 1185: regs.fp[reg] /= src; ! 1186: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1187: break; ! 1188: case 0x25: /* FREM */ ! 1189: regs.fp[reg] = regs.fp[reg] - (double) ((int) (regs.fp[reg] / src + 0.5)) * src; ! 1190: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1191: break; ! 1192: case 0x26: /* FSCALE */ ! 1193: regs.fp[reg] *= exp (log (2.0) * src); ! 1194: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1195: break; ! 1196: case 0x27: /* FSGLMUL */ ! 1197: regs.fp[reg] *= src; ! 1198: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1199: break; ! 1200: case 0x28: /* FSUB */ ! 1201: regs.fp[reg] -= src; ! 1202: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1203: break; ! 1204: case 0x30: /* FSINCOS */ ! 1205: case 0x31: ! 1206: case 0x32: ! 1207: case 0x33: ! 1208: case 0x34: ! 1209: case 0x35: ! 1210: case 0x36: ! 1211: case 0x37: ! 1212: regs.fp[reg] = sin (src); ! 1213: regs.fp[extra & 7] = cos (src); ! 1214: MAKE_FPSR (regs.fpsr, regs.fp[reg]); ! 1215: break; ! 1216: case 0x38: /* FCMP */ ! 1217: { ! 1218: double tmp = regs.fp[reg] - src; ! 1219: regs.fpsr = (tmp == 0 ? 0x4000000 : 0) | (tmp < 0 ? 0x8000000 : 0); ! 1220: } ! 1221: break; ! 1222: case 0x3a: /* FTST */ ! 1223: regs.fpsr = (src == 0 ? 0x4000000 : 0) | (src < 0 ? 0x8000000 : 0); ! 1224: break; ! 1225: default: ! 1226: m68k_setpc (m68k_getpc () - 4); ! 1227: op_illg (opcode); ! 1228: break; ! 1229: } ! 1230: return; ! 1231: } ! 1232: m68k_setpc (m68k_getpc () - 4); ! 1233: op_illg (opcode); ! 1234: } ! 1235: ! 1236: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.