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