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