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