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