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