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