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