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