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