|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68881 emulation
5: *
6: * Copyright 1996 Herman ten Brugge
7: */
8:
9: #include <math.h>
10:
11: #include "sysconfig.h"
12: #include "sysdeps.h"
13:
14: #include "config.h"
15: #include "options.h"
16: #include "events.h"
17: #include "gui.h"
18: #include "memory.h"
19: #include "custom.h"
20: #include "newcpu.h"
21: #include "ersatz.h"
22: #include "readcpu.h"
23:
24: #if CPU_LEVEL >= 2
25:
26: #define DEBUG_FPP 0
27:
28: /* single : S 8*E 23*F */
29: /* double : S 11*E 52*F */
30: /* extended : S 15*E 64*F */
31: /* E = 0 & F = 0 -> 0 */
32: /* E = MAX & F = 0 -> Infin */
33: /* E = MAX & F # 0 -> NotANumber */
34: /* E = biased by 127 (single) ,1023 (double) ,16383 (extended) */
35:
36: static __inline__ double
37: to_single(ULONG value)
38: {
39: double frac;
40:
41: if ((value & 0x7fffffff) == 0) return(0.0);
42: frac = (double)((value & 0x7fffff) | 0x800000) / 8388608.0;
43: if (value & 0x80000000) frac = -frac;
44: return(ldexp(frac, ((value >> 23) & 0xff) - 127));
45: }
46:
47: static __inline__ ULONG
48: from_single(double src)
49: {
50: int expon;
51: ULONG tmp;
52: double frac;
53:
54: if (src == 0.0) return 0;
55: if (src < 0) { tmp = 0x80000000 ; src = -src; }
56: else { tmp = 0; }
57: frac = frexp(src,&expon);
58: frac += 0.5 / 16777216.0;
59: if (frac >= 1.0) { frac /= 2.0; expon++; }
60: return (tmp | (((expon + 127 - 1) & 0xff) << 23) |
61: (((int)(frac * 16777216.0)) & 0x7fffff));
62: }
63:
64: static __inline__ double
65: to_exten(ULONG wrd1,ULONG wrd2,ULONG wrd3)
66: {
67: double frac;
68:
69: if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) return 0.0;
70: frac = (double)wrd2 / 2147483648.0 +
71: (double)wrd3 / 9223372036854775808.0;
72: if (wrd1 & 0x80000000) frac = -frac;
73: return ldexp(frac, ((wrd1 >> 16) & 0x7fff) - 16383);
74: }
75:
76: static __inline__ void
77: from_exten(double src,ULONG *wrd1, ULONG *wrd2, ULONG * wrd3)
78: {
79: int expon;
80: double frac;
81:
82: if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; *wrd3 = 0; return; }
83: if (src < 0) { *wrd1 = 0x80000000 ; src = -src; }
84: else { *wrd1 = 0; }
85: frac = frexp(src,&expon);
86: frac += 0.5 / 18446744073709551616.0;
87: if (frac >= 1.0) { frac /= 2.0; expon++; }
88: *wrd1 |= (((expon + 16383 - 1) & 0x7fff) << 16);
89: *wrd2 = (ULONG)(frac * 4294967296.0);
90: *wrd3 = (ULONG)(frac * 18446744073709551616.0 - *wrd2 * 4294967296.0);
91: }
92:
93: static __inline__ double
94: to_double(ULONG wrd1,ULONG wrd2)
95: {
96: double frac;
97:
98: if ((wrd1 & 0x7fffffff) == 0 && wrd2 == 0) return 0.0;
99: frac = (double)((wrd1 & 0xfffff) | 0x100000) / 1048576.0 +
100: (double)wrd2 / 4503599627370496.0;
101: if (wrd1 & 0x80000000) frac = -frac;
102: return ldexp(frac, ((wrd1 >> 20) & 0x7ff) - 1023);
103: }
104:
105: static __inline__ void
106: from_double(double src,ULONG *wrd1, ULONG *wrd2)
107: {
108: int expon;
109: int tmp;
110: double frac;
111:
112: if (src == 0.0) { *wrd1 = 0; *wrd2 = 0; return; }
113: if (src < 0) { *wrd1 = 0x80000000 ; src = -src; }
114: else { *wrd1 = 0; }
115: frac = frexp(src,&expon);
116: frac += 0.5 / 9007199254740992.0;
117: if (frac >= 1.0) { frac /= 2.0; expon++; }
118: tmp = (ULONG)(frac * 2097152.0);
119: *wrd1 |= (((expon + 1023 - 1) & 0x7ff) << 20) | (tmp & 0xfffff);
120: *wrd2 = (ULONG)(frac * 9007199254740992.0 - tmp * 4294967296.0);
121: }
122:
123: static __inline__ double
124: to_pack(ULONG wrd1,ULONG wrd2,ULONG wrd3)
125: {
126: double d;
127: char *cp;
128: char str[100];
129:
130: cp = str;
131: if (wrd1 & 0x80000000) *cp++ = '-';
132: *cp++ = (wrd1 & 0xf) + '0';
133: *cp++ = '.';
134: *cp++ = ((wrd2 >> 28) & 0xf) + '0';
135: *cp++ = ((wrd2 >> 24) & 0xf) + '0';
136: *cp++ = ((wrd2 >> 20) & 0xf) + '0';
137: *cp++ = ((wrd2 >> 16) & 0xf) + '0';
138: *cp++ = ((wrd2 >> 12) & 0xf) + '0';
139: *cp++ = ((wrd2 >> 8) & 0xf) + '0';
140: *cp++ = ((wrd2 >> 4) & 0xf) + '0';
141: *cp++ = ((wrd2 >> 0) & 0xf) + '0';
142: *cp++ = ((wrd3 >> 28) & 0xf) + '0';
143: *cp++ = ((wrd3 >> 24) & 0xf) + '0';
144: *cp++ = ((wrd3 >> 20) & 0xf) + '0';
145: *cp++ = ((wrd3 >> 16) & 0xf) + '0';
146: *cp++ = ((wrd3 >> 12) & 0xf) + '0';
147: *cp++ = ((wrd3 >> 8) & 0xf) + '0';
148: *cp++ = ((wrd3 >> 4) & 0xf) + '0';
149: *cp++ = ((wrd3 >> 0) & 0xf) + '0';
150: *cp++ = 'E';
151: if (wrd1 & 0x40000000) *cp++ = '-';
152: *cp++ = ((wrd1 >> 24) & 0xf) + '0';
153: *cp++ = ((wrd1 >> 20) & 0xf) + '0';
154: *cp++ = ((wrd1 >> 16) & 0xf) + '0';
155: *cp = 0;
156: sscanf(str,"%le",&d);
157: return d;
158: }
159:
160: static __inline__ void
161: from_pack(double src,ULONG *wrd1, ULONG *wrd2, ULONG * wrd3)
162: {
163: int i;
164: int t;
165: char *cp;
166: char str[100];
167:
168: sprintf(str,"%.16e",src);
169: cp = str;
170: *wrd1 = *wrd2 = *wrd3 = 0;
171: if (*cp == '-') { cp++ ; *wrd1 = 0x80000000; }
172: if (*cp == '+') cp++;
173: *wrd1 |= (*cp++ - '0');
174: if (*cp == '.') cp++;
175: for (i = 0 ; i < 8 ; i++) {
176: *wrd2 <<= 4;
177: if (*cp >= '0' && *cp <= '9')
178: *wrd2 |= *cp++ - '0';
179: }
180: for (i = 0 ; i < 8 ; i++) {
181: *wrd3 <<= 4;
182: if (*cp >= '0' && *cp <= '9')
183: *wrd3 |= *cp++ - '0';
184: }
185: if (*cp == 'e' || *cp == 'E') {
186: cp++;
187: if (*cp == '-') { cp++; *wrd1 |= 0x40000000; }
188: if (*cp == '+') 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:
198: static __inline__ int
199: get_fp_value(ULONG opcode, UWORD extra,double *src)
200: {
201: int size;
202: int mode;
203: int reg;
204: ULONG ad = 0;
205: static int sz1[8] = { 4,4,12,12,2,8,1,0 };
206: static int sz2[8] = { 4,4,12,12,2,8,2,0 };
207:
208: if ((extra & 0x4000) == 0) {
209: *src = regs.fp[(extra >> 10) & 7];
210: return 1;
211: }
212: mode = (opcode >> 3) & 7;
213: reg = opcode & 7;
214: size = (extra >> 10) & 7;
215: switch (mode) {
216: case 0:
217: switch (size) {
218: case 6: *src = (double)(BYTE)regs.d[reg];
219: break;
220: case 4: *src = (double)(WORD)regs.d[reg];
221: break;
222: case 0: *src = (double)(LONG)regs.d[reg];
223: break;
224: case 1: *src = to_single(regs.d[reg]);
225: break;
226: default:
227: return 0;
228: }
229: return 1;
230: case 1:
231: return 0;
232: case 2:
233: ad = regs.a[reg];
234: break;
235: case 3:
236: ad = regs.a[reg];
237: regs.a[reg] += reg == 7 ? sz2[size] : sz1[size];
238: break;
239: case 4:
240: regs.a[reg] -= reg == 7 ? sz2[size] : sz1[size];
241: ad = regs.a[reg];
242: break;
243: case 5:
244: ad = regs.a[reg] + (LONG)(WORD)nextiword();
245: break;
246: case 6:
247: ad = get_disp_ea(regs.a[reg]);
248: break;
249: case 7:
250: switch (reg) {
251: case 0: ad = (LONG)(WORD)nextiword();
252: break;
253: case 1: ad = nextilong();
254: break;
255: case 2: ad = m68k_getpc();
256: ad += (LONG)(WORD)nextiword();
257: break;
258: case 3: ad = get_disp_ea(m68k_getpc());
259: break;
260: case 4: ad = m68k_getpc();
261: m68k_setpc(ad + sz2[size]);
262: break;
263: default:
264: return 0;
265: }
266: }
267: switch (size) {
268: case 0: *src = (double)(LONG)get_long(ad);
269: break;
270: case 1: *src = to_single(get_long(ad));
271: break;
272: case 2: { ULONG wrd1,wrd2,wrd3;
273: wrd1 = get_long(ad);ad+=4;
274: wrd2 = get_long(ad);ad+=4;
275: wrd3 = get_long(ad);
276: *src = to_exten(wrd1,wrd2,wrd3);
277: }
278: break;
279: case 3: { ULONG wrd1,wrd2,wrd3;
280: wrd1 = get_long(ad);ad+=4;
281: wrd2 = get_long(ad);ad+=4;
282: wrd3 = get_long(ad);
283: *src = to_pack(wrd1,wrd2,wrd3);
284: }
285: break;
286: case 4: *src = (double)(WORD)get_word(ad);
287: break;
288: case 5: { ULONG wrd1,wrd2;
289: wrd1 = get_long(ad);ad+=4;
290: wrd2 = get_long(ad);
291: *src = to_double(wrd1,wrd2);
292: }
293: break;
294: case 6: *src = (double)(BYTE)get_byte(ad);
295: break;
296: default:
297: return 0;
298: }
299: return 1;
300: }
301:
302: static __inline__ int
303: put_fp_value(double value, ULONG opcode, UWORD extra)
304: {
305: int size;
306: int mode;
307: int reg;
308: ULONG ad;
309: static int sz1[8] = { 4,4,12,12,2,8,1,0 };
310: static int sz2[8] = { 4,4,12,12,2,8,2,0 };
311:
312: if ((extra & 0x4000) == 0) {
313: regs.fp[(extra >> 10) & 7] = value;
314: return 1;
315: }
316: mode = (opcode >> 3) & 7;
317: reg = opcode & 7;
318: size = (extra >> 10) & 7;
319: ad = -1;
320: switch (mode) {
321: case 0:
322: switch (size) {
323: case 6: regs.d[reg] = ((int)value & 0xff) |
324: (regs.d[reg] & ~0xff);
325: break;
326: case 4: regs.d[reg] = ((int)value & 0xffff) |
327: (regs.d[reg] & ~0xffff);
328: break;
329: case 0: regs.d[reg] = (int)value;
330: break;
331: case 1: regs.d[reg] = from_single(value);
332: break;
333: default:
334: return 0;
335: }
336: return 1;
337: case 1:
338: return 0;
339: case 2:
340: ad = regs.a[reg];
341: break;
342: case 3:
343: ad = regs.a[reg];
344: regs.a[reg] += reg == 7 ? sz2[size] : sz1[size];
345: break;
346: case 4:
347: regs.a[reg] -= reg == 7 ? sz2[size] : sz1[size];
348: ad = regs.a[reg];
349: break;
350: case 5:
351: ad = regs.a[reg] + (LONG)(WORD)nextiword();
352: break;
353: case 6:
354: ad = get_disp_ea(regs.a[reg]);
355: break;
356: case 7:
357: switch (reg) {
358: case 0: ad = (LONG)(WORD)nextiword();
359: break;
360: case 1: ad = nextilong();
361: break;
362: case 2: ad = m68k_getpc();
363: ad += (LONG)(WORD)nextiword();
364: break;
365: case 3: ad = get_disp_ea(m68k_getpc());
366: break;
367: case 4: ad = m68k_getpc();
368: m68k_setpc(ad + sz2[size]);
369: break;
370: default:
371: return 0;
372: }
373: }
374: switch (size) {
375: case 0: put_long(ad,(LONG)value);
376: break;
377: case 1: put_long(ad,from_single(value));
378: break;
379: case 2: { ULONG wrd1,wrd2,wrd3;
380: from_exten(value,&wrd1,&wrd2,&wrd3);
381: put_long(ad,wrd1);ad+=4;
382: put_long(ad,wrd2);ad+=4;
383: put_long(ad,wrd3);
384: }
385: break;
386: case 3: { ULONG wrd1,wrd2,wrd3;
387: from_pack(value,&wrd1,&wrd2,&wrd3);
388: put_long(ad,wrd1);ad+=4;
389: put_long(ad,wrd2);ad+=4;
390: put_long(ad,wrd3);
391: }
392: break;
393: case 4: put_word(ad,(WORD)value);
394: break;
395: case 5: { ULONG wrd1,wrd2;
396: from_double(value,&wrd1,&wrd2);
397: put_long(ad,wrd1);ad+=4;
398: put_long(ad,wrd2);
399: }
400: break;
401: case 6: put_byte(ad,(BYTE)value);
402: break;
403: default:
404: return 0;
405: }
406: return 1;
407: }
408:
409: static __inline__ int
410: get_fp_ad(ULONG opcode,ULONG *ad)
411: {
412: int mode;
413: int reg;
414:
415: mode = (opcode >> 3) & 7;
416: reg = opcode & 7;
417: switch (mode) {
418: case 0:
419: case 1:
420: return 0;
421: case 2:
422: *ad = regs.a[reg];
423: break;
424: case 3:
425: *ad = regs.a[reg];
426: break;
427: case 4:
428: *ad = regs.a[reg];
429: break;
430: case 5:
431: *ad = regs.a[reg] + (LONG)(WORD)nextiword();
432: break;
433: case 6:
434: *ad = get_disp_ea(regs.a[reg]);
435: break;
436: case 7:
437: switch (reg) {
438: case 0: *ad = (LONG)(WORD)nextiword();
439: break;
440: case 1: *ad = nextilong();
441: break;
442: case 2: *ad = m68k_getpc();
443: *ad += (LONG)(WORD)nextiword();
444: break;
445: case 3: *ad = get_disp_ea(m68k_getpc());
446: break;
447: default:
448: return 0;
449: }
450: }
451: return 1;
452: }
453:
454: static __inline__ int
455: fpp_cond(ULONG opcode, int contition)
456: {
457: int N = (regs.fpsr & 0x8000000) != 0;
458: int Z = (regs.fpsr & 0x4000000) != 0;
459: /* int I = (regs.fpsr & 0x2000000) != 0; */
460: int NotANumber = (regs.fpsr & 0x1000000) != 0;
461:
462: switch (contition) {
463: case 0x00: return 0;
464: case 0x01: return Z;
465: case 0x02: return !(NotANumber || Z || N);
466: case 0x03: return Z || !(NotANumber || N);
467: case 0x04: return N && !(NotANumber || Z);
468: case 0x05: return Z || (N && !NotANumber);
469: case 0x06: return !(NotANumber || Z);
470: case 0x07: return !NotANumber;
471: case 0x08: return NotANumber;
472: case 0x09: return NotANumber || Z;
473: case 0x0a: return NotANumber || !(N || Z);
474: case 0x0b: return NotANumber || Z || !N;
475: case 0x0c: return NotANumber || (N && !Z);
476: case 0x0d: return NotANumber || Z || N;
477: case 0x0e: return !Z;
478: case 0x0f: return 1;
479: case 0x10: return 0;
480: case 0x11: return Z;
481: case 0x12: return !(NotANumber || Z || N);
482: case 0x13: return Z || !(NotANumber || N);
483: case 0x14: return N && !(NotANumber || Z);
484: case 0x15: return Z || (N && !NotANumber);
485: case 0x16: return !(NotANumber || Z);
486: case 0x17: return !NotANumber;
487: case 0x18: return NotANumber;
488: case 0x19: return NotANumber || Z;
489: case 0x1a: return NotANumber || !(N || Z);
490: case 0x1b: return NotANumber || Z || !N;
491: case 0x1c: return NotANumber || (Z && N);
492: case 0x1d: return NotANumber || Z || N;
493: case 0x1e: return !Z;
494: case 0x1f: return 1;
495: }
496: return -1;
497: }
498:
499: void
500: fdbcc_opp(ULONG opcode, UWORD extra)
501: {
502: CPTR pc = (ULONG)m68k_getpc();
503: LONG disp = (LONG)(WORD)nextiword();
504: int cc;
505:
506: #if DEBUG_FPP
507: printf("fdbcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
508: #endif
509: cc = fpp_cond(opcode, extra & 0x3f);
510: if (cc == -1) {
511: m68k_setpc(pc-2);
512: op_illg(opcode);
513: }
514: else if (!cc) {
515: regs.d[opcode & 0x7] = (regs.d[opcode & 0x7] & ~0xffff) |
516: ((regs.d[opcode & 0x7]-1) & 0xffff);
517: if ((regs.d[opcode & 0x7] & 0xffff) == 0xffff)
518: m68k_setpc(pc + disp);
519: }
520: }
521:
522: void
523: fscc_opp(ULONG opcode, UWORD extra)
524: {
525: ULONG ad;
526: int cc;
527:
528: #if DEBUG_FPP
529: printf("fscc_opp at %08lx\n",m68k_getpc());fflush(stdout);
530: #endif
531: cc = fpp_cond(opcode, extra & 0x3f);
532: if (cc == -1) {
533: m68k_setpc(m68k_getpc()-2);
534: op_illg(opcode);
535: }
536: else if ((opcode & 0x38) == 0) {
537: regs.d[opcode & 7] = (regs.d[opcode & 7] & ~0xff) |
538: (cc ? 0xff : 0x00);
539: }
540: else {
541: if (get_fp_ad(opcode,&ad) == 0) {
542: m68k_setpc(m68k_getpc()-2);
543: op_illg(opcode);
544: }
545: else
546: put_byte(ad,cc ? 0xff : 0x00);
547: }
548: }
549:
550: void
551: ftrapcc_opp(ULONG opcode, CPTR oldpc)
552: {
553: int cc;
554:
555: #if DEBUG_FPP
556: printf("ftrapcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
557: #endif
558: cc = fpp_cond(opcode, opcode & 0x3f);
559: if (cc == -1) {
560: m68k_setpc(oldpc);
561: op_illg(opcode);
562: }
563: if (cc)
564: Exception(7,oldpc-2);
565: }
566:
567: void
568: fbcc_opp(ULONG opcode, CPTR pc, ULONG extra)
569: {
570: int cc;
571:
572: #if DEBUG_FPP
573: printf("fbcc_opp at %08lx\n",m68k_getpc());fflush(stdout);
574: #endif
575: cc = fpp_cond(opcode, opcode & 0x3f);
576: if (cc == -1) {
577: m68k_setpc(pc);
578: op_illg(opcode);
579: }
580: else if (cc) {
581: if ((opcode & 0x40) == 0)
582: extra = (LONG)(WORD)extra;
583: m68k_setpc(pc + extra);
584: }
585: }
586:
587: void
588: fsave_opp(ULONG opcode)
589: {
590: ULONG ad;
591: int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
592: int i;
593:
594: #if DEBUG_FPP
595: printf("fsave_opp at %08lx\n",m68k_getpc());fflush(stdout);
596: #endif
597: if (get_fp_ad(opcode,&ad) == 0) {
598: op_illg(opcode);
599: return;
600: }
601: if (incr < 0) {
602: ad -= 4;put_long(ad,0x70000000);
603: for (i = 0 ; i < 5 ; i++) {
604: ad -= 4;put_long(ad,0x00000000);
605: }
606: ad -= 4;put_long(ad,0x1f180000);
607: }
608: else {
609: put_long(ad,0x1f180000); ad += 4;
610: for (i = 0 ; i < 5 ; i++) {
611: put_long(ad,0x00000000); ad += 4;
612: }
613: put_long(ad,0x70000000); ad += 4;
614: }
615: if ((opcode & 0x38) == 0x18) regs.a[opcode & 7] = ad;
616: if ((opcode & 0x38) == 0x20) regs.a[opcode & 7] = ad;
617: }
618:
619: void
620: frestore_opp(ULONG opcode)
621: {
622: ULONG ad;
623: ULONG d;
624: int incr = (opcode & 0x38) == 0x20 ? -1 : 1;
625:
626: #if DEBUG_FPP
627: printf("frestore_opp at %08lx\n",m68k_getpc());fflush(stdout);
628: #endif
629: if (get_fp_ad(opcode,&ad) == 0) {
630: op_illg(opcode);
631: return;
632: }
633: if (incr < 0) {
634: ad -= 4; d = get_long(ad);
635: if ((d & 0xff000000) != 0) {
636: if ((d & 0x00ff0000) == 0x00180000)
637: ad -= 6 * 4;
638: else if ((d & 0x00ff0000) == 0x00380000)
639: ad -= 14 * 4;
640: else if ((d & 0x00ff0000) == 0x00b40000)
641: ad -= 45 * 4;
642: }
643: }
644: else {
645: d = get_long(ad); ad += 4;
646: if ((d & 0xff000000) != 0) {
647: if ((d & 0x00ff0000) == 0x00180000)
648: ad += 6 * 4;
649: else if ((d & 0x00ff0000) == 0x00380000)
650: ad += 14 * 4;
651: else if ((d & 0x00ff0000) == 0x00b40000)
652: ad += 45 * 4;
653: }
654: }
655: if ((opcode & 0x38) == 0x18) regs.a[opcode & 7] = ad;
656: if ((opcode & 0x38) == 0x20) regs.a[opcode & 7] = ad;
657: }
658:
659: void
660: fpp_opp(ULONG opcode, UWORD extra)
661: {
662: int reg;
663: double src;
664:
665: #if DEBUG_FPP
666: printf("FPP %04lx %04x at %08lx\n",opcode & 0xffff,extra & 0xffff,
667: m68k_getpc()-4);fflush(stdout);
668: #endif
669: switch ((extra >> 13) & 0x7) {
670: case 3:
671: if (put_fp_value(regs.fp[(extra >> 7) & 7], opcode, extra)== 0){
672: m68k_setpc(m68k_getpc()-2);
673: op_illg(opcode);
674: }
675: return;
676: case 4:
677: case 5:
678: if ((opcode & 0x38) == 0) {
679: if (extra & 0x2000) {
680: if (extra & 0x1000)
681: regs.d[opcode & 7] = regs.fpcr;
682: if (extra & 0x0800)
683: regs.d[opcode & 7] = regs.fpsr;
684: if (extra & 0x0400)
685: regs.d[opcode & 7] = regs.fpiar;
686: }
687: else {
688: if (extra & 0x1000)
689: regs.fpcr = regs.d[opcode & 7];
690: if (extra & 0x0800)
691: regs.fpsr = regs.d[opcode & 7];
692: if (extra & 0x0400)
693: regs.fpiar = regs.d[opcode & 7];
694: }
695: }
696: else if ((opcode & 0x38) == 1) {
697: if (extra & 0x2000) {
698: if (extra & 0x1000)
699: regs.a[opcode & 7] = regs.fpcr;
700: if (extra & 0x0800)
701: regs.a[opcode & 7] = regs.fpsr;
702: if (extra & 0x0400)
703: regs.a[opcode & 7] = regs.fpiar;
704: }
705: else {
706: if (extra & 0x1000)
707: regs.fpcr = regs.a[opcode & 7];
708: if (extra & 0x0800)
709: regs.fpsr = regs.a[opcode & 7];
710: if (extra & 0x0400)
711: regs.fpiar = regs.a[opcode & 7];
712: }
713: }
714: else if ((opcode & 0x3f) == 0x3c) {
715: if ((extra & 0x2000) == 0) {
716: if (extra & 0x1000)
717: regs.fpcr = nextilong();
718: if (extra & 0x0800)
719: regs.fpsr = nextilong();
720: if (extra & 0x0400)
721: regs.fpiar = nextilong();
722: }
723: }
724: else if (extra & 0x2000) {
725: /* FMOVEM FPP->memory */
726: ULONG ad;
727: int incr = 0;
728:
729: if (get_fp_ad(opcode,&ad) == 0) {
730: m68k_setpc(m68k_getpc()-2);
731: op_illg(opcode);
732: return;
733: }
734: if ((opcode & 0x38) == 0x20) {
735: if (extra & 0x1000) incr += 4;
736: if (extra & 0x0800) incr += 4;
737: if (extra & 0x0400) incr += 4;
738: }
739: ad -= incr;
740: if (extra & 0x1000) {
741: put_long(ad,regs.fpcr);ad+=4;
742: }
743: if (extra & 0x0800) {
744: put_long(ad,regs.fpsr);ad+=4;
745: }
746: if (extra & 0x0400) {
747: put_long(ad,regs.fpiar);ad+=4;
748: }
749: ad -= incr;
750: if ((opcode & 0x38) == 0x18) regs.a[opcode & 7] = ad;
751: if ((opcode & 0x38) == 0x20) regs.a[opcode & 7] = ad;
752: }
753: else {
754: /* FMOVEM memory->FPP */
755: ULONG ad;
756:
757: if (get_fp_ad(opcode,&ad) == 0) {
758: m68k_setpc(m68k_getpc()-2);
759: op_illg(opcode);
760: return;
761: }
762: ad = (opcode & 0x38) == 0x20 ? ad-12 : ad;
763: if (extra & 0x1000) {
764: regs.fpcr = get_long(ad);ad+=4;
765: }
766: if (extra & 0x0800) {
767: regs.fpsr = get_long(ad);ad+=4;
768: }
769: if (extra & 0x0400) {
770: regs.fpiar = get_long(ad);ad+=4;
771: }
772: if ((opcode & 0x38) == 0x18) regs.a[opcode & 7] = ad;
773: if ((opcode & 0x38) == 0x20) regs.a[opcode & 7] = ad-12;
774: }
775: return;
776: case 6:
777: case 7:
778: {
779: ULONG ad,list = 0;
780: int incr = 0;
781: if (extra & 0x2000) {
782: /* FMOVEM FPP->memory */
783: if (get_fp_ad(opcode,&ad) == 0) {
784: m68k_setpc(m68k_getpc()-2);
785: op_illg(opcode);
786: return;
787: }
788: switch ((extra >> 11) & 3) {
789: case 0: /* static pred */
790: list = extra & 0xff;
791: incr = -1;
792: break;
793: case 1: /* dynamic pred */
794: list = regs.d[(extra >> 4) & 3] & 0xff;
795: incr = -1;
796: break;
797: case 2: /* static postinc */
798: list = extra & 0xff;
799: incr = 1;
800: break;
801: case 3: /* dynamic postinc */
802: list = regs.d[(extra >> 4) & 3] & 0xff;
803: incr = 1;
804: break;
805: }
806: while (list) {
807: ULONG wrd1,wrd2,wrd3;
808: if (incr < 0) {
809: from_exten(
810: regs.fp[fpp_movem_index2[list]],
811: &wrd1,&wrd2,&wrd3);
812: ad-=4;put_long(ad,wrd3);
813: ad-=4;put_long(ad,wrd2);
814: ad-=4;put_long(ad,wrd1);
815: }
816: else {
817: from_exten(
818: regs.fp[fpp_movem_index1[list]],
819: &wrd1,&wrd2,&wrd3);
820: put_long(ad,wrd1);ad+=4;
821: put_long(ad,wrd2);ad+=4;
822: put_long(ad,wrd3);ad+=4;
823: }
824: list = fpp_movem_next[list];
825: }
826: if ((opcode & 0x38) == 0x18) regs.a[opcode & 7] = ad;
827: if ((opcode & 0x38) == 0x20) regs.a[opcode & 7] = ad;
828: }
829: else {
830: /* FMOVEM memory->FPP */
831: if (get_fp_ad(opcode,&ad) == 0) {
832: m68k_setpc(m68k_getpc()-2);
833: op_illg(opcode);
834: return;
835: }
836: switch ((extra >> 11) & 3) {
837: case 0: /* static pred */
838: list = extra & 0xff;
839: incr = -1;
840: break;
841: case 1: /* dynamic pred */
842: list = regs.d[(extra >> 4) & 3] & 0xff;
843: incr = -1;
844: break;
845: case 2: /* static postinc */
846: list = extra & 0xff;
847: incr = 1;
848: break;
849: case 3: /* dynamic postinc */
850: list = regs.d[(extra >> 4) & 3] & 0xff;
851: incr = 1;
852: break;
853: }
854: while (list) {
855: ULONG wrd1,wrd2,wrd3;
856: if (incr < 0) {
857: ad-=4;wrd3 = get_long(ad);
858: ad-=4;wrd2 = get_long(ad);
859: ad-=4;wrd1 = get_long(ad);
860: regs.fp[fpp_movem_index2[list]] =
861: to_exten(wrd1,wrd2,wrd3);
862: }
863: else {
864: wrd1 = get_long(ad);ad+=4;
865: wrd2 = get_long(ad);ad+=4;
866: wrd3 = get_long(ad);ad+=4;
867: regs.fp[fpp_movem_index1[list]] =
868: to_exten(wrd1,wrd2,wrd3);
869: }
870: list = fpp_movem_next[list];
871: }
872: if ((opcode & 0x38) == 0x18) regs.a[opcode & 7] = ad;
873: if ((opcode & 0x38) == 0x20) regs.a[opcode & 7] = ad;
874: }
875: }
876: return;
877: case 0:
878: case 2:
879: reg = (extra >> 7) & 7;
880: if ((extra & 0xfc00) == 0x5c00) {
881: switch (extra & 0x7f) {
882: case 0x00: regs.fp[reg] = 4.0*atan(1.0); break;
883: case 0x0b: regs.fp[reg] = log10(2.0); break;
884: case 0x0c: regs.fp[reg] = exp(1.0); break;
885: case 0x0d: regs.fp[reg] = log(exp(1.0))/log(2.0); break;
886: case 0x0e: regs.fp[reg] = log(exp(1.0))/log(10.0); break;
887: case 0x0f: regs.fp[reg] = 0.0; break;
888: case 0x30: regs.fp[reg] = log(2.0); break;
889: case 0x31: regs.fp[reg] = log(10.0); break;
890: case 0x32: regs.fp[reg] = 1.0e0; break;
891: case 0x33: regs.fp[reg] = 1.0e1; break;
892: case 0x34: regs.fp[reg] = 1.0e2; break;
893: case 0x35: regs.fp[reg] = 1.0e4; break;
894: case 0x36: regs.fp[reg] = 1.0e8; break;
895: case 0x37: regs.fp[reg] = 1.0e16; break;
896: case 0x38: regs.fp[reg] = 1.0e32; break;
897: case 0x39: regs.fp[reg] = 1.0e64; break;
898: case 0x3a: regs.fp[reg] = 1.0e128; break;
899: case 0x3b: regs.fp[reg] = 1.0e256; break;
900: #if 0
901: case 0x3c: regs.fp[reg] = 1.0e512; break;
902: case 0x3d: regs.fp[reg] = 1.0e1024; break;
903: case 0x3e: regs.fp[reg] = 1.0e2048; break;
904: case 0x3f: regs.fp[reg] = 1.0e4096; break;
905: #endif
906: default:
907: m68k_setpc(m68k_getpc()-2);
908: op_illg(opcode);
909: break;
910: }
911: return;
912: }
913: if (get_fp_value(opcode, extra, &src) == 0) {
914: m68k_setpc(m68k_getpc()-2);
915: op_illg(opcode);
916: return;
917: }
918: switch (extra & 0x7f) {
919: case 0x00: /* FMOVE */
920: regs.fp[reg] = src;
921: break;
922: case 0x01: /* FINT */
923: regs.fp[reg] = (int)(src + 0.5);
924: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
925: (regs.fp[reg] < 0 ? 0x8000000 : 0);
926: break;
927: case 0x02: /* FSINH */
928: regs.fp[reg] = sinh(src);
929: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
930: (regs.fp[reg] < 0 ? 0x8000000 : 0);
931: break;
932: case 0x03: /* FINTRZ */
933: regs.fp[reg] = (int)src;
934: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
935: (regs.fp[reg] < 0 ? 0x8000000 : 0);
936: break;
937: case 0x04: /* FSQRT */
938: regs.fp[reg] = sqrt(src);
939: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
940: (regs.fp[reg] < 0 ? 0x8000000 : 0);
941: break;
942: case 0x06: /* FLOGNP1 */
943: regs.fp[reg] = log(src + 1.0);
944: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
945: (regs.fp[reg] < 0 ? 0x8000000 : 0);
946: break;
947: case 0x08: /* FETOXM1 */
948: regs.fp[reg] = exp(src) - 1.0;
949: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
950: (regs.fp[reg] < 0 ? 0x8000000 : 0);
951: break;
952: case 0x09: /* FTANH */
953: regs.fp[reg] = tanh(src);
954: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
955: (regs.fp[reg] < 0 ? 0x8000000 : 0);
956: break;
957: case 0x0a: /* FATAN */
958: regs.fp[reg] = atan(src);
959: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
960: (regs.fp[reg] < 0 ? 0x8000000 : 0);
961: break;
962: case 0x0c: /* FASIN */
963: regs.fp[reg] = asin(src);
964: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
965: (regs.fp[reg] < 0 ? 0x8000000 : 0);
966: break;
967: case 0x0d: /* FATANH */
968: #ifdef __bebox__
969: printf("atanh\n");
970: #else
971: regs.fp[reg] = atanh(src);
972: #endif
973: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
974: (regs.fp[reg] < 0 ? 0x8000000 : 0);
975: break;
976: case 0x0e: /* FSIN */
977: regs.fp[reg] = sin(src);
978: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
979: (regs.fp[reg] < 0 ? 0x8000000 : 0);
980: break;
981: case 0x0f: /* FTAN */
982: regs.fp[reg] = tan(src);
983: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
984: (regs.fp[reg] < 0 ? 0x8000000 : 0);
985: break;
986: case 0x10: /* FETOX */
987: regs.fp[reg] = exp(src);
988: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
989: (regs.fp[reg] < 0 ? 0x8000000 : 0);
990: break;
991: case 0x11: /* FTWOTOX */
992: regs.fp[reg] = pow(2.0,src);
993: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
994: (regs.fp[reg] < 0 ? 0x8000000 : 0);
995: break;
996: case 0x12: /* FTENTOX */
997: regs.fp[reg] = pow(10.0,src);
998: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
999: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1000: break;
1001: case 0x14: /* FLOGN */
1002: regs.fp[reg] = log(src);
1003: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1004: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1005: break;
1006: case 0x15: /* FLOG10 */
1007: regs.fp[reg] = log10(src);
1008: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1009: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1010: break;
1011: case 0x16: /* FLOG2 */
1012: regs.fp[reg] = log(src) / log(2.0);
1013: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1014: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1015: break;
1016: case 0x18: /* FABS */
1017: regs.fp[reg] = src < 0 ? -src : src;
1018: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1019: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1020: break;
1021: case 0x19: /* FCOSH */
1022: regs.fp[reg] = cosh(src);
1023: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1024: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1025: break;
1026: case 0x1a: /* FNEG */
1027: regs.fp[reg] = -src;
1028: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1029: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1030: break;
1031: case 0x1c: /* FACOS */
1032: regs.fp[reg] = acos(src);
1033: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1034: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1035: break;
1036: case 0x1d: /* FCOS */
1037: regs.fp[reg] = cos(src);
1038: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1039: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1040: break;
1041: case 0x1e: /* FGETEXP */
1042: { int expon;
1043: frexp(src,&expon);
1044: regs.fp[reg] = (double)(expon-1);
1045: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1046: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1047: }
1048: break;
1049: case 0x1f: /* FGETMAN */
1050: { int expon;
1051: regs.fp[reg] = frexp(src,&expon) * 2.0;
1052: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1053: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1054: }
1055: break;
1056: case 0x20: /* FDIV */
1057: regs.fp[reg] /= src;
1058: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1059: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1060: break;
1061: case 0x21: /* FMOD */
1062: regs.fp[reg] = regs.fp[reg] -
1063: (double)((int)(regs.fp[reg] / src)) * src;
1064: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1065: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1066: break;
1067: case 0x22: /* FADD */
1068: regs.fp[reg] += src;
1069: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1070: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1071: break;
1072: case 0x23: /* FMUL */
1073: regs.fp[reg] *= src;
1074: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1075: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1076: break;
1077: case 0x24: /* FSGLDIV */
1078: regs.fp[reg] /= src;
1079: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1080: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1081: break;
1082: case 0x25: /* FREM */
1083: regs.fp[reg] = regs.fp[reg] -
1084: (double)((int)(regs.fp[reg] / src + 0.5)) * src;
1085: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1086: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1087: break;
1088: case 0x26: /* FSCALE */
1089: regs.fp[reg] *= exp(log(2.0)*src);
1090: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1091: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1092: break;
1093: case 0x27: /* FSGLMUL */
1094: regs.fp[reg] *= src;
1095: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1096: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1097: break;
1098: case 0x28: /* FSUB */
1099: regs.fp[reg] -= src;
1100: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1101: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1102: break;
1103: case 0x30: /* FSINCOS */
1104: case 0x31:
1105: case 0x32:
1106: case 0x33:
1107: case 0x34:
1108: case 0x35:
1109: case 0x36:
1110: case 0x37:
1111: regs.fp[reg] = sin(src);
1112: regs.fp[extra & 7] = cos(src);
1113: regs.fpsr = (regs.fp[reg] == 0 ? 0x4000000 : 0) |
1114: (regs.fp[reg] < 0 ? 0x8000000 : 0);
1115: break;
1116: case 0x38: /* FCMP */
1117: { double tmp = regs.fp[reg] - src;
1118: regs.fpsr = (tmp == 0 ? 0x4000000 : 0) |
1119: (tmp < 0 ? 0x8000000 : 0);
1120: }
1121: break;
1122: case 0x3a: /* FTST */
1123: regs.fpsr = (src == 0 ? 0x4000000 : 0) |
1124: (src < 0 ? 0x8000000 : 0);
1125: break;
1126: default:
1127: m68k_setpc(m68k_getpc()-2);
1128: op_illg(opcode);
1129: break;
1130: }
1131: return;
1132: }
1133: m68k_setpc(m68k_getpc()-2);
1134: op_illg(opcode);
1135: }
1136:
1137: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.