]> git.sesse.net Git - pistorm/blob - m68kfpu.c
Merge pull request #9 from shanshe/wip-crap
[pistorm] / m68kfpu.c
1 // SPDX-License-Identifier: MIT
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5
6 #include "softfloat/softfloat.h"
7 float_status status;
8
9 extern void exit(int);
10
11 static void fatalerror(char *format, ...) {
12       va_list ap;
13       va_start(ap,format);
14       vfprintf(stderr,format,ap);  // JFF: fixed. Was using fprintf and arguments were wrong
15       va_end(ap);
16       exit(1);
17 }
18
19 #define FPCC_N                  0x08000000
20 #define FPCC_Z                  0x04000000
21 #define FPCC_I                  0x02000000
22 #define FPCC_NAN                0x01000000
23
24 #define FPES_OE      0x00002000
25 #define FPAE_IOP     0x00000080
26
27 #define DOUBLE_INFINITY                                 (unsigned long long)(0x7ff0000000000000)
28 #define DOUBLE_EXPONENT                                 (unsigned long long)(0x7ff0000000000000)
29 #define DOUBLE_MANTISSA                                 (unsigned long long)(0x000fffffffffffff)
30
31 /*----------------------------------------------------------------------------
32 | Returns 1 if the extended double-precision floating-point value `a' is a
33 | NaN; otherwise returns 0.
34 *----------------------------------------------------------------------------*/
35
36 flag floatx80_is_nan( floatx80 a )
37 {
38
39     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (uint64_t) ( a.low<<1 );
40
41 }
42
43
44 // masks for packed dwords, positive k-factor
45 static uint32 pkmask2[18] =
46 {
47         0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000,
48         0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff,
49         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
50         0xffffffff, 0xffffffff, 0xffffffff
51 };
52
53 static uint32 pkmask3[18] =
54 {
55         0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56         0xf0000000, 0xff000000, 0xfff00000, 0xffff0000,
57         0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff,
58 };
59
60 static inline double fx80_to_double(floatx80 fx)
61 {
62         uint64 d;
63         double *foo;
64
65         foo = (double *)&d;
66
67         d = floatx80_to_float64(fx, &status);
68
69         return *foo;
70 }
71
72 static inline floatx80 double_to_fx80(double in)
73 {
74         uint64 *d;
75
76         d = (uint64 *)&in;
77
78         return float64_to_floatx80(*d, &status);
79 }
80
81 static inline floatx80 load_extended_float80(uint32 ea)
82 {
83         uint32 d1,d2;
84         uint16 d3;
85         floatx80 fp;
86
87         d3 = m68ki_read_16(ea);
88         d1 = m68ki_read_32(ea+4);
89         d2 = m68ki_read_32(ea+8);
90
91         fp.high = d3;
92         fp.low = ((uint64)d1<<32) | (d2 & 0xffffffff);
93
94         return fp;
95 }
96
97 static inline void store_extended_float80(uint32 ea, floatx80 fpr)
98 {
99         m68ki_write_16(ea+0, fpr.high);
100         m68ki_write_16(ea+2, 0);
101         m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff);
102         m68ki_write_32(ea+8, fpr.low&0xffffffff);
103 }
104
105 static inline floatx80 load_pack_float80(uint32 ea)
106 {
107         uint32 dw1, dw2, dw3;
108         floatx80 result;
109         double tmp;
110         char str[128], *ch;
111
112         dw1 = m68ki_read_32(ea);
113         dw2 = m68ki_read_32(ea+4);
114         dw3 = m68ki_read_32(ea+8);
115
116         ch = &str[0];
117         if (dw1 & 0x80000000)   // mantissa sign
118         {
119                 *ch++ = '-';
120         }
121         *ch++ = (char)((dw1 & 0xf) + '0');
122         *ch++ = '.';
123         *ch++ = (char)(((dw2 >> 28) & 0xf) + '0');
124         *ch++ = (char)(((dw2 >> 24) & 0xf) + '0');
125         *ch++ = (char)(((dw2 >> 20) & 0xf) + '0');
126         *ch++ = (char)(((dw2 >> 16) & 0xf) + '0');
127         *ch++ = (char)(((dw2 >> 12) & 0xf) + '0');
128         *ch++ = (char)(((dw2 >> 8)  & 0xf) + '0');
129         *ch++ = (char)(((dw2 >> 4)  & 0xf) + '0');
130         *ch++ = (char)(((dw2 >> 0)  & 0xf) + '0');
131         *ch++ = (char)(((dw3 >> 28) & 0xf) + '0');
132         *ch++ = (char)(((dw3 >> 24) & 0xf) + '0');
133         *ch++ = (char)(((dw3 >> 20) & 0xf) + '0');
134         *ch++ = (char)(((dw3 >> 16) & 0xf) + '0');
135         *ch++ = (char)(((dw3 >> 12) & 0xf) + '0');
136         *ch++ = (char)(((dw3 >> 8)  & 0xf) + '0');
137         *ch++ = (char)(((dw3 >> 4)  & 0xf) + '0');
138         *ch++ = (char)(((dw3 >> 0)  & 0xf) + '0');
139         *ch++ = 'E';
140         if (dw1 & 0x40000000)   // exponent sign
141         {
142                 *ch++ = '-';
143         }
144         *ch++ = (char)(((dw1 >> 24) & 0xf) + '0');
145         *ch++ = (char)(((dw1 >> 20) & 0xf) + '0');
146         *ch++ = (char)(((dw1 >> 16) & 0xf) + '0');
147         *ch = '\0';
148
149         sscanf(str, "%le", &tmp);
150
151         result = double_to_fx80(tmp);
152
153         return result;
154 }
155
156 static inline void store_pack_float80(uint32 ea, int k, floatx80 fpr)
157 {
158         uint32 dw1, dw2, dw3;
159         char str[128], *ch;
160         int i, j, exp;
161
162         dw1 = dw2 = dw3 = 0;
163         ch = &str[0];
164
165         sprintf(str, "%.16e", fx80_to_double(fpr));
166
167         if (*ch == '-')
168         {
169                 ch++;
170                 dw1 = 0x80000000;
171         }
172
173         if (*ch == '+')
174         {
175                 ch++;
176         }
177
178         dw1 |= (*ch++ - '0');
179
180         if (*ch == '.')
181         {
182                 ch++;
183         }
184
185         // handle negative k-factor here
186         if ((k <= 0) && (k >= -13))
187         {
188                 exp = 0;
189                 for (i = 0; i < 3; i++)
190                 {
191                         if (ch[18+i] >= '0' && ch[18+i] <= '9')
192                         {
193                                 exp = (exp << 4) | (ch[18+i] - '0');
194                         }
195                 }
196
197                 if (ch[17] == '-')
198                 {
199                         exp = -exp;
200                 }
201
202                 k = -k;
203                 // last digit is (k + exponent - 1)
204                 k += (exp - 1);
205
206                 // round up the last significant mantissa digit
207                 if (ch[k+1] >= '5')
208                 {
209                         ch[k]++;
210                 }
211
212                 // zero out the rest of the mantissa digits
213                 for (j = (k+1); j < 16; j++)
214                 {
215                         ch[j] = '0';
216                 }
217
218                 // now zero out K to avoid tripping the positive K detection below
219                 k = 0;
220         }
221
222         // crack 8 digits of the mantissa
223         for (i = 0; i < 8; i++)
224         {
225                 dw2 <<= 4;
226                 if (*ch >= '0' && *ch <= '9')
227                 {
228                         dw2 |= *ch++ - '0';
229                 }
230         }
231
232         // next 8 digits of the mantissa
233         for (i = 0; i < 8; i++)
234         {
235                 dw3 <<= 4;
236                 if (*ch >= '0' && *ch <= '9')
237                 dw3 |= *ch++ - '0';
238         }
239
240         // handle masking if k is positive
241         if (k >= 1)
242         {
243                 if (k <= 17)
244                 {
245                         dw2 &= pkmask2[k];
246                         dw3 &= pkmask3[k];
247                 }
248                 else
249                 {
250                         dw2 &= pkmask2[17];
251                         dw3 &= pkmask3[17];
252 //                      m68ki_cpu.fpcr |=  (need to set OPERR bit)
253                 }
254         }
255
256         // finally, crack the exponent
257         if (*ch == 'e' || *ch == 'E')
258         {
259                 ch++;
260                 if (*ch == '-')
261                 {
262                         ch++;
263                         dw1 |= 0x40000000;
264                 }
265
266                 if (*ch == '+')
267                 {
268                         ch++;
269                 }
270
271                 j = 0;
272                 for (i = 0; i < 3; i++)
273                 {
274                         if (*ch >= '0' && *ch <= '9')
275                         {
276                                 j = (j << 4) | (*ch++ - '0');
277                         }
278                 }
279
280                 dw1 |= (j << 16);
281         }
282
283         m68ki_write_32(ea, dw1);
284         m68ki_write_32(ea+4, dw2);
285         m68ki_write_32(ea+8, dw3);
286 }
287
288 static inline void SET_CONDITION_CODES(floatx80 reg)
289 {
290 //  u64 *regi;
291
292 //  regi = (u64 *)&reg;
293
294         REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN);
295
296         // sign flag
297         if (reg.high & 0x8000)
298         {
299                 REG_FPSR |= FPCC_N;
300         }
301
302         // zero flag
303         if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0))
304         {
305                 REG_FPSR |= FPCC_Z;
306         }
307
308         // infinity flag
309         if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0))
310         {
311                 REG_FPSR |= FPCC_I;
312         }
313
314         // NaN flag
315         if (floatx80_is_nan(reg))
316         {
317                 REG_FPSR |= FPCC_NAN;
318         }
319 }
320
321 static inline int TEST_CONDITION(int condition)
322 {
323         int n = (REG_FPSR & FPCC_N) != 0;
324         int z = (REG_FPSR & FPCC_Z) != 0;
325         int nan = (REG_FPSR & FPCC_NAN) != 0;
326         int r = 0;
327         switch (condition)
328         {
329                 case 0x10:
330                 case 0x00:              return 0;                                       // False
331
332                 case 0x11:
333                 case 0x01:              return (z);                                     // Equal
334
335                 case 0x12:
336                 case 0x02:              return (!(nan || z || n));                      // Greater Than
337
338                 case 0x13:
339                 case 0x03:              return (z || !(nan || n));                      // Greater or Equal
340
341                 case 0x14:
342                 case 0x04:              return (n && !(nan || z));                      // Less Than
343
344                 case 0x15:
345                 case 0x05:              return (z || (n && !nan));                      // Less Than or Equal
346
347                 case 0x16:
348                 case 0x06:              return !nan && !z;
349
350                 case 0x17:
351                 case 0x07:              return !nan;
352
353                 case 0x18:
354                 case 0x08:              return nan;
355
356                 case 0x19:
357                 case 0x09:              return nan || z;
358
359                 case 0x1a:
360                 case 0x0a:              return (nan || !(n || z));                      // Not Less Than or Equal
361
362                 case 0x1b:
363                 case 0x0b:              return (nan || z || !n);                        // Not Less Than
364
365                 case 0x1c:
366                 case 0x0c:              return (nan || (n && !z));                      // Not Greater or Equal Than
367
368                 case 0x1d:
369                 case 0x0d:              return (nan || z || n);                         // Not Greater Than
370
371                 case 0x1e:
372                 case 0x0e:              return (!z);                                    // Not Equal
373
374                 case 0x1f:
375                 case 0x0f:              return 1;                                       // True
376
377                 default:                fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition);
378         }
379
380         return r;
381 }
382
383 static uint8 READ_EA_8(int ea)
384 {
385         int mode = (ea >> 3) & 0x7;
386         int reg = (ea & 0x7);
387
388         switch (mode)
389         {
390                 case 0:         // Dn
391                 {
392                         return REG_D[reg];
393                 }
394                 case 2:         // (An)
395                 {
396                         uint32 ea = REG_A[reg];
397                         return m68ki_read_8(ea);
398                 }
399                 case 3:     // (An)+
400                 {
401                         uint32 ea = EA_AY_PI_8();
402                         return m68ki_read_8(ea);
403                 }
404                 case 4:     // -(An)
405                 {
406                         uint32 ea = EA_AY_PD_8();
407                         return m68ki_read_8(ea);
408                 }
409                 case 5:         // (d16, An)
410                 {
411                         uint32 ea = EA_AY_DI_8();
412                         return m68ki_read_8(ea);
413                 }
414                 case 6:         // (An) + (Xn) + d8
415                 {
416                         uint32 ea = EA_AY_IX_8();
417                         return m68ki_read_8(ea);
418                 }
419                 case 7:
420                 {
421                         switch (reg)
422                         {
423                                 case 0:         // (xxx).W
424                                 {
425                                         uint32 ea = (uint32)OPER_I_16();
426                                         return m68ki_read_8(ea);
427                                 }
428                                 case 1:         // (xxx).L
429                                 {
430                                         uint32 d1 = OPER_I_16();
431                                         uint32 d2 = OPER_I_16();
432                                         uint32 ea = (d1 << 16) | d2;
433                                         return m68ki_read_8(ea);
434                                 }
435                                 case 2:     // (d16, PC)
436                                 {
437                                         uint32 ea = EA_PCDI_8();
438                                         return m68ki_read_8(ea);
439                                 }
440                                 case 3:     // (PC) + (Xn) + d8
441                                 {
442                                         uint32 ea =  EA_PCIX_8();
443                                         return m68ki_read_8(ea);
444                                 }
445                                 case 4:         // #<data>
446                                 {
447                                         return  OPER_I_8();
448                                 }
449                                 default:        fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
450                         }
451                         break;
452                 }
453                 default:        fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
454         }
455
456         return 0;
457 }
458
459 static uint16 READ_EA_16(int ea)
460 {
461         int mode = (ea >> 3) & 0x7;
462         int reg = (ea & 0x7);
463
464         switch (mode)
465         {
466                 case 0:         // Dn
467                 {
468                         return (uint16)(REG_D[reg]);
469                 }
470                 case 2:         // (An)
471                 {
472                         uint32 ea = REG_A[reg];
473                         return m68ki_read_16(ea);
474                 }
475                 case 3:     // (An)+
476                 {
477                         uint32 ea = EA_AY_PI_16();
478                         return m68ki_read_16(ea);
479                 }
480                 case 4:     // -(An)
481                 {
482                         uint32 ea = EA_AY_PD_16();
483                         return m68ki_read_16(ea);
484                 }
485                 case 5:         // (d16, An)
486                 {
487                         uint32 ea = EA_AY_DI_16();
488                         return m68ki_read_16(ea);
489                 }
490                 case 6:         // (An) + (Xn) + d8
491                 {
492                         uint32 ea = EA_AY_IX_16();
493                         return m68ki_read_16(ea);
494                 }
495                 case 7:
496                 {
497                         switch (reg)
498                         {
499                                 case 0:         // (xxx).W
500                                 {
501                                         uint32 ea = (uint32)OPER_I_16();
502                                         return m68ki_read_16(ea);
503                                 }
504                                 case 1:         // (xxx).L
505                                 {
506                                         uint32 d1 = OPER_I_16();
507                                         uint32 d2 = OPER_I_16();
508                                         uint32 ea = (d1 << 16) | d2;
509                                         return m68ki_read_16(ea);
510                                 }
511                                 case 2:     // (d16, PC)
512                                 {
513                                         uint32 ea = EA_PCDI_16();
514                                         return m68ki_read_16(ea);
515                                 }
516                                 case 3:     // (PC) + (Xn) + d8
517                                 {
518                                         uint32 ea =  EA_PCIX_16();
519                                         return m68ki_read_16(ea);
520                                 }
521                                 case 4:         // #<data>
522                                 {
523                                         return OPER_I_16();
524                                 }
525
526                                 default:        fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
527                         }
528                         break;
529                 }
530                 default:        fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
531         }
532
533         return 0;
534 }
535
536 static uint32 READ_EA_32(int ea)
537 {
538         int mode = (ea >> 3) & 0x7;
539         int reg = (ea & 0x7);
540
541         switch (mode)
542         {
543                 case 0:         // Dn
544                 {
545                         return REG_D[reg];
546                 }
547                 case 2:         // (An)
548                 {
549                         uint32 ea = REG_A[reg];
550                         return m68ki_read_32(ea);
551                 }
552                 case 3:         // (An)+
553                 {
554                         uint32 ea = EA_AY_PI_32();
555                         return m68ki_read_32(ea);
556                 }
557                 case 4:         // -(An)
558                 {
559                         uint32 ea = EA_AY_PD_32();
560                         return m68ki_read_32(ea);
561                 }
562                 case 5:         // (d16, An)
563                 {
564                         uint32 ea = EA_AY_DI_32();
565                         return m68ki_read_32(ea);
566                 }
567                 case 6:         // (An) + (Xn) + d8
568                 {
569                         uint32 ea = EA_AY_IX_32();
570                         return m68ki_read_32(ea);
571                 }
572                 case 7:
573                 {
574                         switch (reg)
575                         {
576                                 case 0:         // (xxx).W
577                                 {
578                                         uint32 ea = (uint32)OPER_I_16();
579                                         return m68ki_read_32(ea);
580                                 }
581                                 case 1:         // (xxx).L
582                                 {
583                                         uint32 d1 = OPER_I_16();
584                                         uint32 d2 = OPER_I_16();
585                                         uint32 ea = (d1 << 16) | d2;
586                                         return m68ki_read_32(ea);
587                                 }
588                                 case 2:         // (d16, PC)
589                                 {
590                                         uint32 ea = EA_PCDI_32();
591                                         return m68ki_read_32(ea);
592                                 }
593                                 case 3:     // (PC) + (Xn) + d8
594                                 {
595                                         uint32 ea =  EA_PCIX_32();
596                                         return m68ki_read_32(ea);
597                                 }
598                                 case 4:         // #<data>
599                                 {
600                                         return  OPER_I_32();
601                                 }
602                                 default:        fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
603                         }
604                         break;
605                 }
606                 default:        fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
607         }
608         return 0;
609 }
610
611 static uint64 READ_EA_64(int ea)
612 {
613         int mode = (ea >> 3) & 0x7;
614         int reg = (ea & 0x7);
615         uint32 h1, h2;
616
617         switch (mode)
618         {
619                 case 2:         // (An)
620                 {
621                         uint32 ea = REG_A[reg];
622                         h1 = m68ki_read_32(ea+0);
623                         h2 = m68ki_read_32(ea+4);
624                         return  (uint64)(h1) << 32 | (uint64)(h2);
625                 }
626                 case 3:         // (An)+
627                 {
628                         uint32 ea = REG_A[reg];
629                         REG_A[reg] += 8;
630                         h1 = m68ki_read_32(ea+0);
631                         h2 = m68ki_read_32(ea+4);
632                         return  (uint64)(h1) << 32 | (uint64)(h2);
633                 }
634                 case 4:     // -(An)
635                 {
636                         uint32 ea = REG_A[reg]-8;
637                         REG_A[reg] -= 8;
638                         h1 = m68ki_read_32(ea+0);
639                         h2 = m68ki_read_32(ea+4);
640                         return  (uint64)(h1) << 32 | (uint64)(h2);
641                 }
642                 case 5:         // (d16, An)
643                 {
644                         uint32 ea = EA_AY_DI_32();
645                         h1 = m68ki_read_32(ea+0);
646                         h2 = m68ki_read_32(ea+4);
647                         return  (uint64)(h1) << 32 | (uint64)(h2);
648                 }
649                 case 6:     // (An) + (Xn) + d8
650                 {
651                         uint32 ea = EA_AY_IX_32();
652                         h1 = m68ki_read_32(ea+0);
653                         h2 = m68ki_read_32(ea+4);
654                         return  (uint64)(h1) << 32 | (uint64)(h2);
655                 }
656                 case 7:
657                 {
658                         switch (reg)
659                         {
660                                 case 1:     // (xxx).L
661                                 {
662                                         uint32 d1 = OPER_I_16();
663                                         uint32 d2 = OPER_I_16();
664                                         uint32 ea = (d1 << 16) | d2;
665                                         return (uint64)(m68ki_read_32(ea)) << 32 | (uint64)(m68ki_read_32(ea+4));
666                                 }
667                                 case 3:     // (PC) + (Xn) + d8
668                                 {
669                                         uint32 ea =  EA_PCIX_32();
670                                         h1 = m68ki_read_32(ea+0);
671                                         h2 = m68ki_read_32(ea+4);
672                                         return  (uint64)(h1) << 32 | (uint64)(h2);
673                                 }
674                                 case 4:         // #<data>
675                                 {
676                                         h1 = OPER_I_32();
677                                         h2 = OPER_I_32();
678                                         return  (uint64)(h1) << 32 | (uint64)(h2);
679                                 }
680                                 case 2:         // (d16, PC)
681                                 {
682                                         uint32 ea = EA_PCDI_32();
683                                         h1 = m68ki_read_32(ea+0);
684                                         h2 = m68ki_read_32(ea+4);
685                                         return  (uint64)(h1) << 32 | (uint64)(h2);
686                                 }
687                                 default:        fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
688                         }
689                         break;
690                 }
691                 default:        fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
692         }
693
694         return 0;
695 }
696
697
698 static floatx80 READ_EA_FPE(uint32 ea)
699 {
700         floatx80 fpr;
701         int mode = (ea >> 3) & 0x7;
702         int reg = (ea & 0x7);
703
704         switch (mode)
705         {
706                 case 2:         // (An)
707                 {
708                         uint32 ea = REG_A[reg];
709                         fpr = load_extended_float80(ea);
710                         break;
711                 }
712
713                 case 3:         // (An)+
714                 {
715                         uint32 ea = REG_A[reg];
716                         REG_A[reg] += 12;
717                         fpr = load_extended_float80(ea);
718                         break;
719                 }
720                 case 4:     // -(An)
721                 {
722                         uint32 ea = REG_A[reg]-12;
723                         REG_A[reg] -= 12;
724                         fpr = load_extended_float80(ea);
725                         break;
726                 }
727       case 5:           // (d16, An)
728                 {
729                         // FIXME: will fail for fmovem
730                         uint32 ea = EA_AY_DI_32();
731                         fpr = load_extended_float80(ea);
732                 break;
733                 }
734                 case 6:     // (An) + (Xn) + d8
735                 {
736                         // FIXME: will fail for fmovem
737                         uint32 ea = EA_AY_IX_32();
738                         fpr = load_extended_float80(ea);
739                         break;
740                 }
741
742                 case 7: // extended modes
743                 {
744                         switch (reg)
745                         {
746                                 case 1:     // (xxx)
747                                         {
748                                                 uint32 d1 = OPER_I_16();
749                                                 uint32 d2 = OPER_I_16();
750                                                 uint32 ea = (d1 << 16) | d2;
751                                                 fpr = load_extended_float80(ea);
752                                         }
753                                         break;
754
755                                 case 2: // (d16, PC)
756                                         {
757                                                 uint32 ea = EA_PCDI_32();
758                                                 fpr = load_extended_float80(ea);
759                                         }
760                                         break;
761
762                                 case 3: // (d16,PC,Dx.w)
763                                         {
764                                                 uint32 ea = EA_PCIX_32();
765                                                 fpr = load_extended_float80(ea);
766                                         }
767                                         break;
768
769                                 case 4: // immediate (JFF)
770                                         {
771                                                 uint32 ea = REG_PC;
772                                                 fpr = load_extended_float80(ea);
773                                                 REG_PC += 12;
774                                         }
775                                         break;
776
777                                 default:
778                                         fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
779                                         break;
780                         }
781                 }
782                 break;
783
784                 default:        fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break;
785         }
786
787         return fpr;
788 }
789
790 static floatx80 READ_EA_PACK(int ea)
791 {
792         floatx80 fpr;
793         int mode = (ea >> 3) & 0x7;
794         int reg = (ea & 0x7);
795
796         switch (mode)
797         {
798                 case 2:         // (An)
799                 {
800                         uint32 ea = REG_A[reg];
801                         fpr = load_pack_float80(ea);
802                         break;
803                 }
804
805                 case 3:         // (An)+
806                 {
807                         uint32 ea = REG_A[reg];
808                         REG_A[reg] += 12;
809                         fpr = load_pack_float80(ea);
810                         break;
811                 }
812
813                 case 7: // extended modes
814                 {
815                         switch (reg)
816                         {
817                                 case 3: // (d16,PC,Dx.w)
818                                         {
819                                                 uint32 ea = EA_PCIX_32();
820                                                 fpr = load_pack_float80(ea);
821                                         }
822                                         break;
823
824                                 default:
825                                         fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
826                                         break;
827                         }
828                 }
829                 break;
830
831                 default:        fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break;
832         }
833
834         return fpr;
835 }
836
837 static void WRITE_EA_8(int ea, uint8 data)
838 {
839         int mode = (ea >> 3) & 0x7;
840         int reg = (ea & 0x7);
841
842         switch (mode)
843         {
844                 case 0:         // Dn
845                 {
846                         REG_D[reg] = data;
847                         break;
848                 }
849                 case 2:         // (An)
850                 {
851                         uint32 ea = REG_A[reg];
852                         m68ki_write_8(ea, data);
853                         break;
854                 }
855                 case 3:         // (An)+
856                 {
857                         uint32 ea = EA_AY_PI_8();
858                         m68ki_write_8(ea, data);
859                         break;
860                 }
861                 case 4:         // -(An)
862                 {
863                         uint32 ea = EA_AY_PD_8();
864                         m68ki_write_8(ea, data);
865                         break;
866                 }
867                 case 5:         // (d16, An)
868                 {
869                         uint32 ea = EA_AY_DI_8();
870                         m68ki_write_8(ea, data);
871                         break;
872                 }
873                 case 6:         // (An) + (Xn) + d8
874                 {
875                         uint32 ea = EA_AY_IX_8();
876                         m68ki_write_8(ea, data);
877                         break;
878                 }
879                 case 7:
880                 {
881                         switch (reg)
882                         {
883                                 case 1:         // (xxx).B
884                                 {
885                                         uint32 d1 = OPER_I_16();
886                                         uint32 d2 = OPER_I_16();
887                                         uint32 ea = (d1 << 16) | d2;
888                                         m68ki_write_8(ea, data);
889                                         break;
890                                 }
891                                 case 2:         // (d16, PC)
892                                 {
893                                         uint32 ea = EA_PCDI_16();
894                                         m68ki_write_8(ea, data);
895                                         break;
896                                 }
897                                 default:        fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
898                         }
899                         break;
900                 }
901                 default:        fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
902         }
903 }
904
905 static void WRITE_EA_16(int ea, uint16 data)
906 {
907         int mode = (ea >> 3) & 0x7;
908         int reg = (ea & 0x7);
909
910         switch (mode)
911         {
912                 case 0:         // Dn
913                 {
914                         REG_D[reg] = data;
915                         break;
916                 }
917                 case 2:         // (An)
918                 {
919                         uint32 ea = REG_A[reg];
920                         m68ki_write_16(ea, data);
921                         break;
922                 }
923                 case 3:         // (An)+
924                 {
925                         uint32 ea = EA_AY_PI_16();
926                         m68ki_write_16(ea, data);
927                         break;
928                 }
929                 case 4:         // -(An)
930                 {
931                         uint32 ea = EA_AY_PD_16();
932                         m68ki_write_16(ea, data);
933                         break;
934                 }
935                 case 5:         // (d16, An)
936                 {
937                         uint32 ea = EA_AY_DI_16();
938                         m68ki_write_16(ea, data);
939                         break;
940                 }
941                 case 6:         // (An) + (Xn) + d8
942                 {
943                         uint32 ea = EA_AY_IX_16();
944                         m68ki_write_16(ea, data);
945                         break;
946                 }
947                 case 7:
948                 {
949                         switch (reg)
950                         {
951                                 case 1:         // (xxx).W
952                                 {
953                                         uint32 d1 = OPER_I_16();
954                                         uint32 d2 = OPER_I_16();
955                                         uint32 ea = (d1 << 16) | d2;
956                                         m68ki_write_16(ea, data);
957                                         break;
958                                 }
959                                 case 2:         // (d16, PC)
960                                 {
961                                         uint32 ea = EA_PCDI_16();
962                                         m68ki_write_16(ea, data);
963                                         break;
964                                 }
965                                 default:        fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
966                         }
967                         break;
968                 }
969                 default:        fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
970         }
971 }
972
973 static void WRITE_EA_32(int ea, uint32 data)
974 {
975         int mode = (ea >> 3) & 0x7;
976         int reg = (ea & 0x7);
977
978         switch (mode)
979         {
980                 case 0:         // Dn
981                 {
982                         REG_D[reg] = data;
983                         break;
984                 }
985                 case 1:         // An
986                 {
987                         REG_A[reg] = data;
988                         break;
989                 }
990                 case 2:         // (An)
991                 {
992                         uint32 ea = REG_A[reg];
993                         m68ki_write_32(ea, data);
994                         break;
995                 }
996                 case 3:         // (An)+
997                 {
998                         uint32 ea = EA_AY_PI_32();
999                         m68ki_write_32(ea, data);
1000                         break;
1001                 }
1002                 case 4:         // -(An)
1003                 {
1004                         uint32 ea = EA_AY_PD_32();
1005                         m68ki_write_32(ea, data);
1006                         break;
1007                 }
1008                 case 5:         // (d16, An)
1009                 {
1010                         uint32 ea = EA_AY_DI_32();
1011                         m68ki_write_32(ea, data);
1012                         break;
1013                 }
1014                 case 6:         // (An) + (Xn) + d8
1015                 {
1016                         uint32 ea = EA_AY_IX_32();
1017                         m68ki_write_32(ea, data);
1018                         break;
1019                 }
1020                 case 7:
1021                 {
1022                         switch (reg)
1023                         {
1024                                 case 0:     // (xxx).W
1025                                 {
1026                                         uint32 ea = OPER_I_16();
1027                                         m68ki_write_32(ea, data);
1028                                         break;
1029                                 }
1030                                 case 1:         // (xxx).L
1031                                 {
1032                                         uint32 d1 = OPER_I_16();
1033                                         uint32 d2 = OPER_I_16();
1034                                         uint32 ea = (d1 << 16) | d2;
1035                                         m68ki_write_32(ea, data);
1036                                         break;
1037                                 }
1038                                 case 2:         // (d16, PC)
1039                                 {
1040                                         uint32 ea = EA_PCDI_32();
1041                                         m68ki_write_32(ea, data);
1042                                         break;
1043                                 }
1044                                 default:        fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
1045                         }
1046                         break;
1047                 }
1048                 default:        fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
1049         }
1050 }
1051
1052 static void WRITE_EA_64(int ea, uint64 data)
1053 {
1054         int mode = (ea >> 3) & 0x7;
1055         int reg = (ea & 0x7);
1056
1057         switch (mode)
1058         {
1059                 case 2:         // (An)
1060                 {
1061                         uint32 ea = REG_A[reg];
1062                         m68ki_write_32(ea, (uint32)(data >> 32));
1063                         m68ki_write_32(ea+4, (uint32)(data));
1064                         break;
1065                 }
1066                 case 3:     // (An)+
1067                 {
1068                         uint32 ea = REG_A[reg];
1069                         REG_A[reg] += 8;
1070                         m68ki_write_32(ea+0, (uint32)(data >> 32));
1071                         m68ki_write_32(ea+4, (uint32)(data));
1072                         break;
1073                 }
1074                 case 4:         // -(An)
1075                 {
1076                         uint32 ea;
1077                         REG_A[reg] -= 8;
1078                         ea = REG_A[reg];
1079                         m68ki_write_32(ea+0, (uint32)(data >> 32));
1080                         m68ki_write_32(ea+4, (uint32)(data));
1081                         break;
1082                 }
1083                 case 5:         // (d16, An)
1084                 {
1085                         uint32 ea = EA_AY_DI_32();
1086                         m68ki_write_32(ea+0, (uint32)(data >> 32));
1087                         m68ki_write_32(ea+4, (uint32)(data));
1088                         break;
1089                 }
1090                 case 6:     // (An) + (Xn) + d8
1091                 {
1092                         uint32 ea = EA_AY_IX_32();
1093                         m68ki_write_32(ea+0, (uint32)(data >> 32));
1094                         m68ki_write_32(ea+4, (uint32)(data));
1095                         break;
1096                 }
1097                 case 7:
1098                 {
1099                         switch (reg)
1100                         {
1101                                 case 1:     // (xxx).L
1102                                 {
1103                                         uint32 d1 = OPER_I_16();
1104                                         uint32 d2 = OPER_I_16();
1105                                         uint32 ea = (d1 << 16) | d2;
1106                                         m68ki_write_32(ea+0, (uint32)(data >> 32));
1107                                         m68ki_write_32(ea+4, (uint32)(data));
1108                                         break;
1109                                 }
1110                                 case 2:     // (d16, PC)
1111                                 {
1112                                         uint32 ea = EA_PCDI_32();
1113                                         m68ki_write_32(ea+0, (uint32)(data >> 32));
1114                                         m68ki_write_32(ea+4, (uint32)(data));
1115                                         break;
1116                                 }
1117                                 default:    fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
1118                         }
1119                         break;
1120                 }
1121                 default:        fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (uint32)(data >> 32), (uint32)(data), REG_PC);
1122         }
1123 }
1124
1125 static void WRITE_EA_FPE(uint32 ea, floatx80 fpr)
1126 {
1127         int mode = (ea >> 3) & 0x7;
1128         int reg = (ea & 0x7);
1129
1130         switch (mode)
1131         {
1132                 case 2:         // (An)
1133                 {
1134                         uint32 ea;
1135                         ea = REG_A[reg];
1136                         store_extended_float80(ea, fpr);
1137                         break;
1138                 }
1139
1140                 case 3:         // (An)+
1141                 {
1142                         uint32 ea;
1143                         ea = REG_A[reg];
1144                         store_extended_float80(ea, fpr);
1145                         REG_A[reg] += 12;
1146                         break;
1147                 }
1148
1149                 case 4:         // -(An)
1150                 {
1151                         uint32 ea;
1152                         REG_A[reg] -= 12;
1153                         ea = REG_A[reg];
1154                         store_extended_float80(ea, fpr);
1155                         break;
1156                 }
1157           case 5:               // (d16, An)
1158                 {
1159                   uint32 ea = EA_AY_DI_32();
1160                   store_extended_float80(ea, fpr);
1161                  break;
1162
1163                 }
1164                 case 7:
1165                 {
1166                         switch (reg)
1167                         {
1168                                 default:        fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
1169                         }
1170                         break;
1171                 }
1172                 default:        fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
1173         }
1174 }
1175
1176 static void WRITE_EA_PACK(int ea, int k, floatx80 fpr)
1177 {
1178         int mode = (ea >> 3) & 0x7;
1179         int reg = (ea & 0x7);
1180
1181         switch (mode)
1182         {
1183                 case 2:         // (An)
1184                 {
1185                         uint32 ea;
1186                         ea = REG_A[reg];
1187                         store_pack_float80(ea, k, fpr);
1188                         break;
1189                 }
1190
1191                 case 3:         // (An)+
1192                 {
1193                         uint32 ea;
1194                         ea = REG_A[reg];
1195                         store_pack_float80(ea, k, fpr);
1196                         REG_A[reg] += 12;
1197                         break;
1198                 }
1199
1200                 case 4:         // -(An)
1201                 {
1202                         uint32 ea;
1203                         REG_A[reg] -= 12;
1204                         ea = REG_A[reg];
1205                         store_pack_float80(ea, k, fpr);
1206                         break;
1207                 }
1208
1209                 case 7:
1210                 {
1211                         switch (reg)
1212                         {
1213                                 default:        fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
1214                         }
1215                 }
1216                 break;
1217                 default:        fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
1218         }
1219 }
1220
1221
1222 static void fpgen_rm_reg(uint16 w2)
1223 {
1224         int ea = REG_IR & 0x3f;
1225         int rm = (w2 >> 14) & 0x1;
1226         int src = (w2 >> 10) & 0x7;
1227         int dst = (w2 >>  7) & 0x7;
1228         int opmode = w2 & 0x7f;
1229         floatx80 source;
1230
1231         // fmovecr #$f, fp0     f200 5c0f
1232
1233         if (rm)
1234         {
1235                 switch (src)
1236                 {
1237                         case 0:         // Long-Word Integer
1238                         {
1239                                 sint32 d = READ_EA_32(ea);
1240                                 source = int32_to_floatx80(d);
1241                                 break;
1242                         }
1243                         case 1:         // Single-precision Real
1244                         {
1245                                 uint32 d = READ_EA_32(ea);
1246                                 source = float32_to_floatx80(d, &status);
1247                                 break;
1248                         }
1249                         case 2:         // Extended-precision Real
1250                         {
1251                                 source = READ_EA_FPE(ea);
1252                                 break;
1253                         }
1254                         case 3:         // Packed-decimal Real
1255                         {
1256                                 source = READ_EA_PACK(ea);
1257                                 break;
1258                         }
1259                         case 4:         // Word Integer
1260                         {
1261                                 sint16 d = READ_EA_16(ea);
1262                                 source = int32_to_floatx80((sint32)d);
1263                                 break;
1264                         }
1265                         case 5:         // Double-precision Real
1266                         {
1267                                 uint64 d = READ_EA_64(ea);
1268
1269                                 source = float64_to_floatx80(d, &status);
1270                                 break;
1271                         }
1272                         case 6:         // Byte Integer
1273                         {
1274                                 sint8 d = READ_EA_8(ea);
1275                                 source = int32_to_floatx80((sint32)d);
1276                                 break;
1277                         }
1278                         case 7:         // FMOVECR load from constant ROM
1279                         {
1280                                 switch (w2 & 0x7f)
1281                                 {
1282                                         case 0x0:       // Pi
1283                                                 source.high = 0x4000;
1284                                                 source.low = U64(0xc90fdaa22168c235);
1285                                                 break;
1286
1287                                         case 0xb:       // log10(2)
1288                                                 source.high = 0x3ffd;
1289                                                 source.low = U64(0x9a209a84fbcff798);
1290                                                 break;
1291
1292                                         case 0xc:       // e
1293                                                 source.high = 0x4000;
1294                                                 source.low = U64(0xadf85458a2bb4a9b);
1295                                                 break;
1296
1297                                         case 0xd:       // log2(e)
1298                                                 source.high = 0x3fff;
1299                                                 source.low = U64(0xb8aa3b295c17f0bc);
1300                                                 break;
1301
1302                                         case 0xe:       // log10(e)
1303                                                 source.high = 0x3ffd;
1304                                                 source.low = U64(0xde5bd8a937287195);
1305                                                 break;
1306
1307                                         case 0xf:       // 0.0
1308                                                 source = int32_to_floatx80((sint32)0);
1309                                                 break;
1310
1311                                         case 0x30:      // ln(2)
1312                                                 source.high = 0x3ffe;
1313                                                 source.low = U64(0xb17217f7d1cf79ac);
1314                                                 break;
1315
1316                                         case 0x31:      // ln(10)
1317                                                 source.high = 0x4000;
1318                                                 source.low = U64(0x935d8dddaaa8ac17);
1319                                                 break;
1320
1321                                         case 0x32:      // 1 (or 100?  manuals are unclear, but 1 would make more sense)
1322                                                 source = int32_to_floatx80((sint32)1);
1323                                                 break;
1324
1325                                         case 0x33:      // 10^1
1326                                                 source = int32_to_floatx80((sint32)10);
1327                                                 break;
1328
1329                                         case 0x34:      // 10^2
1330                                                 source = int32_to_floatx80((sint32)10*10);
1331                                                 break;
1332                                         case 0x35:  // 10^4
1333                                                 source = int32_to_floatx80((sint32)1000*10);
1334                                                 break;
1335
1336                                         case 0x36:  // 1.0e8
1337                                                 source = int32_to_floatx80((sint32)10000000*10);
1338                                                 break;
1339
1340                                         case 0x37:  // 1.0e16 - can't get the right precision from s32 so go "direct" with constants from h/w
1341                                                 source.high = 0x4034;
1342                                                 source.low = U64(0x8e1bc9bf04000000);
1343                                                 break;
1344
1345                                         case 0x38:  // 1.0e32
1346                                                 source.high = 0x4069;
1347                                                 source.low = U64(0x9dc5ada82b70b59e);
1348                                                 break;
1349
1350                                         case 0x39:  // 1.0e64
1351                                                 source.high = 0x40d3;
1352                                                 source.low = U64(0xc2781f49ffcfa6d5);
1353                                                 break;
1354
1355                                         case 0x3a:  // 1.0e128
1356                                                 source.high = 0x41a8;
1357                                                 source.low = U64(0x93ba47c980e98ce0);
1358                                                 break;
1359
1360                                         case 0x3b:  // 1.0e256
1361                                                 source.high = 0x4351;
1362                                                 source.low = U64(0xaa7eebfb9df9de8e);
1363                                                 break;
1364
1365                                         case 0x3c:  // 1.0e512
1366                                                 source.high = 0x46a3;
1367                                                 source.low = U64(0xe319a0aea60e91c7);
1368                                                 break;
1369
1370                                         case 0x3d:  // 1.0e1024
1371                                                 source.high = 0x4d48;
1372                                                 source.low = U64(0xc976758681750c17);
1373                                                 break;
1374
1375                                         case 0x3e:  // 1.0e2048
1376                                                 source.high = 0x5a92;
1377                                                 source.low = U64(0x9e8b3b5dc53d5de5);
1378                                                 break;
1379
1380                                         case 0x3f:  // 1.0e4096
1381                                                 source.high = 0x7525;
1382                                                 source.low = U64(0xc46052028a20979b);
1383                                                 break;
1384
1385
1386                                         default:
1387                                                 fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC-4);
1388                                                 break;
1389                                 }
1390
1391                                 // handle it right here, the usual opmode bits aren't valid in the FMOVECR case
1392                                 REG_FP[dst] = source;
1393                                 //FIXME mame doesn't use SET_CONDITION_CODES here
1394                                 SET_CONDITION_CODES(REG_FP[dst]); // JFF when destination is a register, we HAVE to update FPCR
1395                                 USE_CYCLES(4);
1396                                 return;
1397                         }
1398                         default:        fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC-4);
1399                 }
1400         }
1401         else
1402         {
1403                 source = REG_FP[src];
1404         }
1405
1406
1407
1408         switch (opmode)
1409         {
1410                 case 0x00:              // FMOVE
1411                 {
1412                         REG_FP[dst] = source;
1413                         SET_CONDITION_CODES(REG_FP[dst]);
1414                         USE_CYCLES(4);
1415                         break;
1416                 }
1417                 case 0x01:              // FINT
1418                 {
1419                         sint32 temp;
1420                         temp = floatx80_to_int32(source, &status);
1421                         REG_FP[dst] = int32_to_floatx80(temp);
1422                         //FIXME mame doesn't use SET_CONDITION_CODES here
1423                         SET_CONDITION_CODES(REG_FP[dst]);  // JFF needs update condition codes
1424                         USE_CYCLES(4);
1425                         break;
1426                 }
1427                 case 0x02:              // FSINH
1428                 {
1429                         REG_FP[dst] = floatx80_sinh(source, &status);
1430                         SET_CONDITION_CODES(REG_FP[dst]);
1431                         USE_CYCLES(75);
1432                         break;
1433                 }
1434                 case 0x03:              // FINTRZ
1435                 {
1436                         sint32 temp;
1437                         temp = floatx80_to_int32_round_to_zero(source, &status);
1438                         REG_FP[dst] = int32_to_floatx80(temp);
1439                         //FIXME mame doesn't use SET_CONDITION_CODES here
1440                         SET_CONDITION_CODES(REG_FP[dst]);  // JFF needs update condition codes
1441                         break;
1442                 }
1443                 case 0x04:              // FSQRT
1444                 {
1445                         REG_FP[dst] = floatx80_sqrt(source, &status);
1446                         SET_CONDITION_CODES(REG_FP[dst]);
1447                         USE_CYCLES(109);
1448                         break;
1449                 }
1450                 case 0x06:      // FLOGNP1
1451                 {
1452                         REG_FP[dst] = floatx80_lognp1 (source, &status);
1453                         SET_CONDITION_CODES(REG_FP[dst]);
1454                         USE_CYCLES(594); // for MC68881
1455                         break;
1456                 }
1457                 case 0x08:      // FETOXM1
1458                 {
1459                         REG_FP[dst] = floatx80_etoxm1(source, &status);
1460                         SET_CONDITION_CODES(REG_FP[dst]);
1461                         USE_CYCLES(6);
1462                         break;
1463                 }
1464                 case 0x09:      // FTANH
1465                 {
1466                         REG_FP[dst] = floatx80_tanh(source, &status);
1467                         SET_CONDITION_CODES(REG_FP[dst]);
1468                         USE_CYCLES(75);
1469                         break;
1470                 }
1471                 case 0x0a:      // FATAN
1472                 {
1473                         REG_FP[dst] = floatx80_atan(source, &status);
1474                         SET_CONDITION_CODES(REG_FP[dst]);
1475                         USE_CYCLES(75);
1476                         break;
1477                 }
1478                 case 0x0c:      // FASIN
1479                 {
1480                         REG_FP[dst] = floatx80_asin(source, &status);
1481                         SET_CONDITION_CODES(REG_FP[dst]);
1482                         USE_CYCLES(75);
1483                         break;
1484                 }
1485                 case 0x0d:      // FATANH
1486                 {
1487                         REG_FP[dst] = floatx80_atanh(source, &status);
1488                         SET_CONDITION_CODES(REG_FP[dst]);
1489                         USE_CYCLES(75);
1490                         break;
1491                 }
1492                 case 0x0e:      // FSIN
1493                 {
1494                         REG_FP[dst] = floatx80_sin(source, &status);
1495                         SET_CONDITION_CODES(REG_FP[dst]);
1496                         USE_CYCLES(75);
1497                         break;
1498                 }
1499                 case 0x0f:      // FTAN
1500                 {
1501                         REG_FP[dst] = floatx80_tan(source, &status);
1502                         SET_CONDITION_CODES(REG_FP[dst]);
1503                         USE_CYCLES(75);
1504                         break;
1505                 }
1506                 case 0x10:      // FETOX
1507                 {
1508                         REG_FP[dst] = floatx80_etox(source, &status);
1509                         SET_CONDITION_CODES(REG_FP[dst]);
1510                         USE_CYCLES(75);
1511                         break;
1512                 }
1513                 case 0x11:      // FTWOTOX
1514                 {
1515                         REG_FP[dst] = floatx80_twotox(source, &status);
1516                         SET_CONDITION_CODES(REG_FP[dst]);
1517                         USE_CYCLES(75);
1518                         break;
1519                 }
1520                 case 0x12:      // FTENTOX
1521                 {
1522                         REG_FP[dst] = floatx80_tentox(source, &status);
1523                         SET_CONDITION_CODES(REG_FP[dst]);
1524                         USE_CYCLES(75);
1525                         break;
1526                 }
1527                 case 0x14:      // FLOGN
1528                 {
1529                         REG_FP[dst] = floatx80_logn(source, &status);
1530                         SET_CONDITION_CODES(REG_FP[dst]);
1531                         USE_CYCLES(548); // for MC68881
1532                         break;
1533                 }
1534                 case 0x15:      // FLOG10
1535                 {
1536                         REG_FP[dst] = floatx80_log10(source, &status);
1537                         SET_CONDITION_CODES(REG_FP[dst]);
1538                         USE_CYCLES(604); // for MC68881
1539                         break;
1540                 }
1541                 case 0x16:      // FLOG2
1542                 {
1543                         REG_FP[dst] = floatx80_log2(source, &status);
1544                         SET_CONDITION_CODES(REG_FP[dst]);
1545                         USE_CYCLES(604); // for MC68881
1546                         break;
1547                 }
1548                 case 0x18:              // FABS
1549                 {
1550                         REG_FP[dst] = source;
1551                         REG_FP[dst].high &= 0x7fff;
1552                         SET_CONDITION_CODES(REG_FP[dst]);
1553                         USE_CYCLES(3);
1554                         break;
1555                 }
1556                 case 0x19:      // FCOSH
1557                 {
1558                         REG_FP[dst] = floatx80_cosh(source, &status);
1559                         SET_CONDITION_CODES(REG_FP[dst]);
1560                         USE_CYCLES(64);
1561                         break;
1562                 }
1563                 case 0x1a:              // FNEG
1564                 {
1565                         REG_FP[dst] = source;
1566                         REG_FP[dst].high ^= 0x8000;
1567                         SET_CONDITION_CODES(REG_FP[dst]);
1568                         USE_CYCLES(3);
1569                         break;
1570                 }
1571                 case 0x1c:      // FACOS
1572                 {
1573                         REG_FP[dst] = floatx80_acos(source, &status);
1574                         SET_CONDITION_CODES(REG_FP[dst]);
1575                         USE_CYCLES(604); // for MC68881
1576                         break;
1577                         break;
1578                 }
1579                 case 0x1d:      // FCOS
1580                 {
1581                         REG_FP[dst] = floatx80_cos(source, &status);
1582                         SET_CONDITION_CODES(REG_FP[dst]);
1583                         USE_CYCLES(75);
1584                         break;
1585                 }
1586                 case 0x1e:              // FGETEXP
1587                 {
1588                         REG_FP[dst] = floatx80_getexp(source, &status);
1589                         SET_CONDITION_CODES(REG_FP[dst]);
1590                         USE_CYCLES(6);
1591                         break;
1592                 }
1593                 case 0x1f:      // FGETMAN
1594                 {
1595                         REG_FP[dst] = floatx80_getman(source, &status);
1596                         SET_CONDITION_CODES(REG_FP[dst]);
1597                         USE_CYCLES(6);
1598                         break;
1599                 }
1600                 case 0x60:              // FSDIVS (JFF) (source has already been converted to floatx80)
1601                 case 0x20:              // FDIV
1602                 {
1603                         REG_FP[dst] = floatx80_div(REG_FP[dst], source, &status);
1604                         //FIXME mame doesn't use SET_CONDITION_CODES here
1605                         SET_CONDITION_CODES(REG_FP[dst]); // JFF
1606                         USE_CYCLES(43);
1607                         break;
1608                 }
1609                 case 0x21:      // FMOD
1610                 {
1611                         sint8 const mode = status.float_rounding_mode;
1612                         status.float_rounding_mode = float_round_to_zero;
1613                         uint64_t q;
1614                         flag s;
1615                         REG_FP[dst] = floatx80_rem(REG_FP[dst], source, &q, &s, &status);
1616                         SET_CONDITION_CODES(REG_FP[dst]);
1617                         status.float_rounding_mode = mode;
1618                         USE_CYCLES(43);   // guess
1619                         break;
1620                 }
1621                 case 0x22:              // FADD
1622                 {
1623                         REG_FP[dst] = floatx80_add(REG_FP[dst], source, &status);
1624                         SET_CONDITION_CODES(REG_FP[dst]);
1625                         USE_CYCLES(9);
1626                         break;
1627                 }
1628                 case 0x63:              // FSMULS (JFF) (source has already been converted to floatx80)
1629                 case 0x23:              // FMUL
1630                 {
1631                         REG_FP[dst] = floatx80_mul(REG_FP[dst], source, &status);
1632                         SET_CONDITION_CODES(REG_FP[dst]);
1633                         USE_CYCLES(11);
1634                         break;
1635                 }
1636                 case 0x24:      // FSGLDIV
1637                 {
1638                         REG_FP[dst] = floatx80_sgldiv(REG_FP[dst], source, &status);
1639                         USE_CYCLES(43); //  // ? (value is from FDIV)
1640                         break;
1641                 }
1642                 case 0x25:              // FREM
1643                 {
1644                         sint8 const mode = status.float_rounding_mode;
1645                         status.float_rounding_mode = float_round_nearest_even;
1646                         uint64_t q;
1647                         flag s;
1648                         REG_FP[dst] = floatx80_rem(REG_FP[dst], source, &q, &s, &status);
1649                         SET_CONDITION_CODES(REG_FP[dst]);
1650                         status.float_rounding_mode = mode;
1651                         USE_CYCLES(43); // guess
1652                         break;
1653                 }
1654                 case 0x26:      // FSCALE
1655                 {
1656                         REG_FP[dst] = floatx80_scale(REG_FP[dst], source, &status);
1657                         SET_CONDITION_CODES(REG_FP[dst]);
1658                         USE_CYCLES(46);   // (better?) guess
1659                         break;
1660                 }
1661                 case 0x27:      // FSGLMUL
1662                 {
1663                         REG_FP[dst] = floatx80_sglmul(REG_FP[dst], source, &status);
1664                         SET_CONDITION_CODES(REG_FP[dst]);
1665                         USE_CYCLES(11); // ? (value is from FMUL)
1666                         break;
1667                 }
1668                 case 0x28:              // FSUB
1669                 {
1670                         REG_FP[dst] = floatx80_sub(REG_FP[dst], source, &status);
1671                         SET_CONDITION_CODES(REG_FP[dst]);
1672                         USE_CYCLES(9);
1673                         break;
1674                 }
1675                 case 0x30:      // FSINCOS
1676                 case 0x31:      // FSINCOS
1677                 case 0x32:      // FSINCOS
1678                 case 0x33:      // FSINCOS
1679                 case 0x34:      // FSINCOS
1680                 case 0x35:      // FSINCOS
1681                 case 0x36:      // FSINCOS
1682                 case 0x37:      // FSINCOS
1683                 {
1684                         REG_FP[dst] = floatx80_cos(source, &status);
1685                         REG_FP[w2&7] = floatx80_sin(source, &status);
1686                         SET_CONDITION_CODES(REG_FP[dst]);
1687                         USE_CYCLES(75);
1688
1689                         break;
1690                 }
1691                 case 0x38:              // FCMP
1692                 {
1693                         floatx80 res;
1694                         res = floatx80_sub(REG_FP[dst], source, &status);
1695                         SET_CONDITION_CODES(res);
1696                         USE_CYCLES(7);
1697                         break;
1698                 }
1699                 case 0x3a:              // FTST
1700                 {
1701                         floatx80 res;
1702                         res = source;
1703                         SET_CONDITION_CODES(res);
1704                         USE_CYCLES(7);
1705                         break;
1706                 }
1707
1708                 default:        fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4);
1709         }
1710 }
1711
1712 static void fmove_reg_mem(uint16 w2)
1713 {
1714         int ea = REG_IR & 0x3f;
1715         int src = (w2 >>  7) & 0x7;
1716         int dst = (w2 >> 10) & 0x7;
1717         int k = (w2 & 0x7f);
1718
1719         switch (dst)
1720         {
1721                 case 0:         // Long-Word Integer
1722                 {
1723                         sint32 d = (sint32)floatx80_to_int32(REG_FP[src], &status);
1724                         WRITE_EA_32(ea, d);
1725                         break;
1726                 }
1727                 case 1:         // Single-precision Real
1728                 {
1729                         uint32 d = floatx80_to_float32(REG_FP[src], &status);
1730                         WRITE_EA_32(ea, d);
1731                         break;
1732                 }
1733                 case 2:         // Extended-precision Real
1734                 {
1735                         WRITE_EA_FPE(ea, REG_FP[src]);
1736                         break;
1737                 }
1738                 case 3:         // Packed-decimal Real with Static K-factor
1739                 {
1740                         // sign-extend k
1741                         k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f);
1742                         WRITE_EA_PACK(ea, k, REG_FP[src]);
1743                         break;
1744                 }
1745                 case 4:         // Word Integer
1746                 {
1747                         sint32 value = floatx80_to_int32(REG_FP[src], &status);
1748                         if (value > 0x7fff || value < -0x8000 )
1749                         {
1750                                 REG_FPSR |= FPES_OE | FPAE_IOP;
1751                         }
1752                         WRITE_EA_16(ea, (sint16)value);
1753                         break;
1754                 }
1755                 case 5:         // Double-precision Real
1756                 {
1757                         uint64 d;
1758
1759                         d = floatx80_to_float64(REG_FP[src], &status);
1760
1761                         WRITE_EA_64(ea, d);
1762                         break;
1763                 }
1764                 case 6:         // Byte Integer
1765                 {
1766                         sint32 value = floatx80_to_int32(REG_FP[src], &status);
1767                         if (value > 127 || value < -128)
1768                         {
1769                                 REG_FPSR |= FPES_OE | FPAE_IOP;
1770                         }
1771                         WRITE_EA_8(ea, (sint8)value);
1772                         break;
1773                 }
1774                 case 7:         // Packed-decimal Real with Dynamic K-factor
1775                 {
1776                         WRITE_EA_PACK(ea, REG_D[k>>4], REG_FP[src]);
1777                         break;
1778                 }
1779         }
1780
1781         USE_CYCLES(12);
1782 }
1783
1784 static void fmove_fpcr(uint16 w2)
1785 {
1786         int ea = REG_IR & 0x3f;
1787         int dir = (w2 >> 13) & 0x1;
1788         int regsel = (w2 >> 10) & 0x7;
1789         int mode = (ea >> 3) & 0x7;
1790
1791         if ((mode == 5) || (mode == 6))
1792         {
1793                 uint32 address = 0xffffffff;    // force a bus error if this doesn't get assigned
1794
1795                 if (mode == 5)
1796                 {
1797                         address = EA_AY_DI_32();
1798                 }
1799                 else if (mode == 6)
1800                 {
1801                         address = EA_AY_IX_32();
1802                 }
1803
1804                 if (dir)        // From system control reg to <ea>
1805                 {
1806                         if (regsel & 4) { m68ki_write_32(address, REG_FPCR); address += 4; }
1807                         if (regsel & 2) { m68ki_write_32(address, REG_FPSR); address += 4; }
1808                         if (regsel & 1) { m68ki_write_32(address, REG_FPIAR); address += 4; }
1809                 }
1810                 else            // From <ea> to system control reg
1811                 {
1812                         if (regsel & 4) { REG_FPCR = m68ki_read_32(address); address += 4; }
1813                         if (regsel & 2) { REG_FPSR = m68ki_read_32(address); address += 4; }
1814                         if (regsel & 1) { REG_FPIAR = m68ki_read_32(address); address += 4; }
1815                 }
1816         }
1817         else
1818         {
1819                 if (dir)    // From system control reg to <ea>
1820                 {
1821                         if (regsel & 4) WRITE_EA_32(ea, REG_FPCR);
1822                         if (regsel & 2) WRITE_EA_32(ea, REG_FPSR);
1823                         if (regsel & 1) WRITE_EA_32(ea, REG_FPIAR);
1824                 }
1825                 else        // From <ea> to system control reg
1826                 {
1827                         if (regsel & 4) REG_FPCR = READ_EA_32(ea);
1828                         if (regsel & 2) REG_FPSR = READ_EA_32(ea);
1829                         if (regsel & 1) REG_FPIAR = READ_EA_32(ea);
1830                 }
1831         }
1832
1833         // FIXME: (2011-12-18 ost)
1834         // rounding_mode and rounding_precision of softfloat.c should be set according to current fpcr
1835         // but:  with this code on Apollo the following programs in /systest/fptest will fail:
1836         // 1. Single Precision Whetstone will return wrong results never the less
1837         // 2. Vector Test will fault with 00040004: reference to illegal address
1838
1839         if ((regsel & 4) && dir == 0)
1840         {
1841                 int rnd = (REG_FPCR >> 4) & 3;
1842                 int prec = (REG_FPCR >> 6) & 3;
1843
1844 //      logerror("m68k_fpsp:fmove_fpcr fpcr=%04x prec=%d rnd=%d\n", m_fpcr, prec, rnd);
1845
1846 #ifdef FLOATX80
1847                 switch (prec)
1848                 {
1849                 case 0: // Extend (X)
1850                         status.floatx80_rounding_precision = 80;
1851                         break;
1852                 case 1: // Single (S)
1853                         status.floatx80_rounding_precision = 32;
1854                         break;
1855                 case 2: // Double (D)
1856                         status.floatx80_rounding_precision = 64;
1857                         break;
1858                 case 3: // Undefined
1859                         status.floatx80_rounding_precision = 80;
1860                         break;
1861                 }
1862 #endif
1863
1864                 switch (rnd)
1865                 {
1866                 case 0: // To Nearest (RN)
1867                         status.float_rounding_mode = float_round_nearest_even;
1868                         break;
1869                 case 1: // To Zero (RZ)
1870                         status.float_rounding_mode = float_round_to_zero;
1871                         break;
1872                 case 2: // To Minus Infinitiy (RM)
1873                         status.float_rounding_mode = float_round_down;
1874                         break;
1875                 case 3: // To Plus Infinitiy (RP)
1876                         status.float_rounding_mode = float_round_up;
1877                         break;
1878                 }
1879         }
1880
1881         USE_CYCLES(10);
1882 }
1883
1884 static void fmovem(uint16 w2)
1885 {
1886         int i;
1887         int ea = REG_IR & 0x3f;
1888         int dir = (w2 >> 13) & 0x1;
1889         int mode = (w2 >> 11) & 0x3;
1890         int reglist = w2 & 0xff;
1891
1892         uint32 mem_addr = 0;
1893         switch (ea >> 3)
1894         {
1895                 case 5:     // (d16, An)
1896                         mem_addr= EA_AY_DI_32();
1897                         break;
1898                 case 6:     // (An) + (Xn) + d8
1899                         mem_addr= EA_AY_IX_32();
1900                         break;
1901         }
1902
1903         if (dir)        // From FP regs to mem
1904         {
1905                 switch (mode)
1906                 {
1907                         case 1: // Dynamic register list, postincrement or control addressing mode.
1908                                 // FIXME: not really tested, but seems to work
1909                                 reglist = REG_D[(reglist >> 4) & 7];
1910                                 /* fall through */
1911                                 /* no break */
1912                         case 0:     // Static register list, predecrement or control addressing mode
1913                         {
1914                                 for (i=0; i < 8; i++)
1915                                 {
1916                                         if (reglist & (1 << i))
1917                                         {
1918                                                 switch (ea >> 3)
1919                                                 {
1920                                                         case 5:     // (d16, An)
1921                                                         case 6:     // (An) + (Xn) + d8
1922                                                                 store_extended_float80(mem_addr, REG_FP[i]);
1923                                                                 mem_addr += 12;
1924                                                                 break;
1925                                                         default:
1926                                                                 WRITE_EA_FPE(ea, REG_FP[i]);
1927                                                                 break;
1928                                                 }
1929
1930                                                 USE_CYCLES(2);
1931                                         }
1932                                 }
1933                                 break;
1934                         }
1935
1936                         case 2:         // Static register list, postdecrement or control addressing mode.     
1937                         {
1938                                 for (i=0; i < 8; i++)
1939                                 {
1940                                         if (reglist & (1 << i))
1941                                         {
1942                                                 switch (ea >> 3)
1943                                                 {
1944                                                         case 5:     // (d16, An)
1945                                                         case 6:     // (An) + (Xn) + d8
1946                                                                 store_extended_float80(mem_addr, REG_FP[7-i]);
1947                                                                 mem_addr += 12;
1948                                                                 break;
1949                                                         default:
1950                                                                 WRITE_EA_FPE(ea, REG_FP[7-i]);
1951                                                                 break;
1952                                                 }
1953
1954                                                 USE_CYCLES(2);
1955                                         }
1956                                 }
1957                                 break;
1958                         }
1959
1960                         default:        fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
1961                 }
1962         }
1963         else            // From mem to FP regs
1964         {
1965                 switch (mode)
1966                 {
1967                         case 3: // Dynamic register list, predecrement addressing mode.
1968                                 // FIXME: not really tested, but seems to work
1969                                 reglist = REG_D[(reglist >> 4) & 7];
1970                                 /* fall through */
1971                                 /* no break */
1972                         case 2:         // Static register list, postincrement or control addressing mode
1973                         {
1974                                 for (i=0; i < 8; i++)
1975                                 {
1976                                         if (reglist & (1 << i))
1977                                         {
1978                                                 switch (ea >> 3)
1979                                                 {
1980                                                         case 5:     // (d16, An)
1981                                                         case 6:     // (An) + (Xn) + d8
1982                                                                 REG_FP[7-i] = load_extended_float80(mem_addr);
1983                                                                 mem_addr += 12;
1984                                                                 break;
1985                                                         default:
1986                                                                 REG_FP[7-i] = READ_EA_FPE(ea);
1987                                                                 break;
1988                                                 }
1989                                                 USE_CYCLES(2);
1990                                         }
1991                                 }
1992                                 break;
1993                         }
1994
1995                         default:        fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
1996                 }
1997         }
1998 }
1999
2000 static void fscc()
2001 {
2002         int ea = REG_IR & 0x3f;
2003         int condition = (sint16)(OPER_I_16());
2004
2005         WRITE_EA_8(ea, TEST_CONDITION(condition) ? 0xff : 0);
2006         USE_CYCLES(7);  // ???
2007 }
2008 static void fbcc16(void)
2009 {
2010         sint32 offset;
2011         int condition = REG_IR & 0x3f;
2012
2013         offset = (sint16)(OPER_I_16());
2014
2015         // TODO: condition and jump!!!
2016         if (TEST_CONDITION(condition))
2017         {
2018                 m68ki_trace_t0();                          /* auto-disable (see m68kcpu.h) */
2019                 m68ki_branch_16(offset-2);
2020         }
2021
2022         USE_CYCLES(7);
2023 }
2024
2025 static void fbcc32(void)
2026 {
2027         sint32 offset;
2028         int condition = REG_IR & 0x3f;
2029
2030         offset = OPER_I_32();
2031
2032         // TODO: condition and jump!!!
2033         if (TEST_CONDITION(condition))
2034         {
2035                 m68ki_trace_t0();                          /* auto-disable (see m68kcpu.h) */
2036                 m68ki_branch_32(offset-4);
2037         }
2038
2039         USE_CYCLES(7);
2040 }
2041
2042
2043 void m68040_fpu_op0()
2044 {
2045         m68ki_cpu.fpu_just_reset = 0;
2046
2047         switch ((REG_IR >> 6) & 0x3)
2048         {
2049                 case 0:
2050                 {
2051                         uint16 w2 = OPER_I_16();
2052                         switch ((w2 >> 13) & 0x7)
2053                         {
2054                                 case 0x0:       // FPU ALU FP, FP
2055                                 case 0x2:       // FPU ALU ea, FP
2056                                 {
2057                                         fpgen_rm_reg(w2);
2058                                         break;
2059                                 }
2060
2061                                 case 0x3:       // FMOVE FP, ea
2062                                 {
2063                                         fmove_reg_mem(w2);
2064                                         break;
2065                                 }
2066
2067                                 case 0x4:       // FMOVEM ea, FPCR
2068                                 case 0x5:       // FMOVEM FPCR, ea
2069                                 {
2070                                         fmove_fpcr(w2);
2071                                         break;
2072                                 }
2073
2074                                 case 0x6:       // FMOVEM ea, list
2075                                 case 0x7:       // FMOVEM list, ea
2076                                 {
2077                                         fmovem(w2);
2078                                         break;
2079                                 }
2080
2081                                 default:        fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4);
2082                         }
2083                         break;
2084                 }
2085
2086                 case 1:           // FBcc disp16
2087                 {
2088                         switch ((REG_IR >> 3) & 0x7) {
2089                         case 1: // FDBcc
2090                                 // TODO:
2091                                 printf("M68kFPU: unimplemented FDBcc main op %d with mode %d at %08X\n", (REG_IR >> 6) & 0x3, (REG_IR >> 3) & 0x7, REG_PC-4);
2092                                 break;
2093                         default: // FScc (?)
2094                                 fscc();
2095                                 return;
2096                         }
2097                         fatalerror("M68kFPU: unimplemented main op %d with mode %d at %08X\n", (REG_IR >> 6) & 0x3, (REG_IR >> 3) & 0x7, REG_PC-4);
2098                         break;
2099                 }
2100                 case 2:     // FBcc disp16
2101                 {
2102                         fbcc16();
2103                         break;
2104                 }
2105                 case 3:     // FBcc disp32
2106                 {
2107                         fbcc32();
2108                         break;
2109                 }
2110
2111                 default:    fatalerror("M68kFPU: unimplemented main op %d\n", (REG_IR >> 6) & 0x3);
2112         }
2113 }
2114
2115 static int perform_fsave(uint32 addr, int inc)
2116 {
2117         if(m68ki_cpu.cpu_type & CPU_TYPE_040)
2118         {
2119                 if(inc)
2120                 {
2121                         m68ki_write_32(addr, 0x41000000);
2122                         return 4 -4;
2123                 }
2124                 else
2125                 {
2126                         m68ki_write_32(addr, 0x41000000);
2127                         return -4 +4;
2128                 }
2129         }
2130
2131         if (inc)
2132         {
2133                 // 68881 IDLE, version 0x1f
2134                 m68ki_write_32(addr, 0x1f180000);
2135                 m68ki_write_32(addr+4, 0);
2136                 m68ki_write_32(addr+8, 0);
2137                 m68ki_write_32(addr+12, 0);
2138                 m68ki_write_32(addr+16, 0);
2139                 m68ki_write_32(addr+20, 0);
2140                 m68ki_write_32(addr+24, 0x70000000);
2141                 return 7*4 -4;
2142         }
2143         else
2144         {
2145                 m68ki_write_32(addr+4-4, 0x70000000);
2146                 m68ki_write_32(addr+4-8, 0);
2147                 m68ki_write_32(addr+4-12, 0);
2148                 m68ki_write_32(addr+4-16, 0);
2149                 m68ki_write_32(addr+4-20, 0);
2150                 m68ki_write_32(addr+4-24, 0);
2151                 m68ki_write_32(addr+4-28, 0x1f180000);
2152                 return -7*4 +4;
2153         }
2154 }
2155
2156 // FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0
2157 static void do_frestore_null(void)
2158 {
2159         int i;
2160
2161         REG_FPCR = 0;
2162         REG_FPSR = 0;
2163         REG_FPIAR = 0;
2164         for (i = 0; i < 8; i++)
2165         {
2166                 REG_FP[i].high = 0x7fff;
2167                 REG_FP[i].low = U64(0xffffffffffffffff);
2168         }
2169
2170         // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL
2171         // The PRM says it's possible to generate a NULL frame, but not how/when/why.  (need the 68881/68882 manual!)
2172         m68ki_cpu.fpu_just_reset = 1;
2173 }
2174
2175 void m68040_do_fsave(uint32 addr, int reg, int inc)
2176 {
2177         if (m68ki_cpu.fpu_just_reset)
2178         {
2179                 m68ki_write_32(addr, 0);
2180         }
2181         else
2182         {
2183                 // we normally generate an IDLE frame
2184                 int delta = perform_fsave(addr, inc);
2185                 if(reg != -1)
2186                         REG_A[reg] += delta;
2187         }
2188 }
2189
2190 void m68040_do_frestore(uint32 addr, int reg)
2191 {
2192         uint32 temp = m68ki_read_32(addr);
2193         // check for nullptr frame
2194         if (temp & 0xff000000)
2195         {
2196                 // we don't handle non-nullptr frames
2197                 m68ki_cpu.fpu_just_reset = 0;
2198
2199                 if (reg != -1)
2200                 {
2201                         uint8 m40 = !!(m68ki_cpu.cpu_type & CPU_TYPE_040);
2202                         // how about an IDLE frame?
2203                         if (!m40 && ((temp & 0x00ff0000) == 0x00180000))
2204                         {
2205                                 REG_A[reg] += 7*4-4;
2206                         }
2207                         else if (m40 && ((temp & 0xffff0000) == 0x41000000))
2208                         {
2209 //                              REG_A[reg] += 4;
2210                         } // check UNIMP
2211                         else if ((temp & 0x00ff0000) == 0x00380000)
2212                         {
2213                                 REG_A[reg] += 14*4;
2214                         } // check BUSY
2215                         else if ((temp & 0x00ff0000) == 0x00b40000)
2216                         {
2217                                 REG_A[reg] += 45*4;
2218                         }
2219                 }
2220         }
2221         else
2222         {
2223                 do_frestore_null();
2224         }
2225 }
2226
2227 void m68040_fpu_op1()
2228 {
2229         int ea = REG_IR & 0x3f;
2230         int mode = (ea >> 3) & 0x7;
2231         int reg = (ea & 0x7);
2232         uint32 addr;
2233
2234         switch ((REG_IR >> 6) & 0x3)
2235         {
2236                 case 0:         // FSAVE <ea>
2237                 {
2238                         switch (mode)
2239                         {
2240                                 case 2: // (An)
2241                                         addr = REG_A[reg];
2242                                         m68040_do_fsave(addr, -1, 1);
2243                                         break;
2244
2245                                 case 3: // (An)+
2246                                         addr = EA_AY_PI_32();
2247                                         printf("FSAVE mode %d, reg A%d=0x%08x\n",mode,reg,REG_A[reg]);
2248                                         m68040_do_fsave(addr, -1, 1); // FIXME: -1 was reg
2249                                         break;
2250
2251                                 case 4: // -(An)
2252                                         addr = EA_AY_PD_32();
2253                                         m68040_do_fsave(addr, reg, 0); // FIXME: -1 was reg
2254                                         break;
2255                                 case 5: // (D16, An)
2256                                         addr = EA_AY_DI_16();
2257                                         m68040_do_fsave(addr, -1, 1);
2258                                         break;
2259
2260                                 case 6: // (An) + (Xn) + d8
2261                                         addr = EA_AY_IX_16();
2262                                         m68040_do_fsave(addr, -1, 1);
2263                                         break;
2264
2265                                 case 7: //
2266                                 {
2267                                         switch (reg)
2268                                         {
2269                                                 case 1:     // (abs32)
2270                                                 {
2271                                                         addr = EA_AL_32();
2272                                                         m68040_do_fsave(addr, -1, 1);
2273                                                         break;
2274                                                 }
2275                                                 case 2:     // (d16, PC)
2276                                                 {
2277                                                         addr = EA_PCDI_16();
2278                                                         m68040_do_fsave(addr, -1, 1);
2279                                                         break;
2280                                                 }
2281                                                 default:
2282                                                         fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2283                                         }
2284                                 }
2285                                 break;
2286
2287                                 default:
2288                                         fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2289                         }
2290                 }
2291                 break;
2292
2293                 case 1:         // FRESTORE <ea>
2294                 {
2295                         switch (mode)
2296                         {
2297                                 case 2: // (An)
2298                                         addr = REG_A[reg];
2299                                         m68040_do_frestore(addr, -1);
2300                                         break;
2301
2302                                 case 3: // (An)+
2303                                         addr = EA_AY_PI_32();
2304                                         m68040_do_frestore(addr, reg);
2305                                         break;
2306
2307                                 case 5: // (D16, An)
2308                                         addr = EA_AY_DI_16();
2309                                         m68040_do_frestore(addr, -1);
2310                                         break;
2311
2312                                 case 6: // (An) + (Xn) + d8
2313                                         addr = EA_AY_IX_16();
2314                                         m68040_do_frestore(addr, -1);
2315                                         break;
2316
2317                                 case 7: //
2318                                 {
2319                                         switch (reg)
2320                                         {
2321                                                 case 1:     // (abs32)
2322                                                 {
2323                                                         addr = EA_AL_32();
2324                                                         m68040_do_frestore(addr, -1);
2325                                                         break;
2326                                                 }
2327                                                 case 2:     // (d16, PC)
2328                                                 {
2329                                                         addr = EA_PCDI_16();
2330                                                         m68040_do_frestore(addr, -1);
2331                                                         break;
2332                                                 }
2333                                                 default:
2334                                                         fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2335                                         }
2336                                 }
2337                                 break;
2338
2339                                 default:
2340                                         fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2341                         }
2342                 }
2343                 break;
2344
2345                 default:    fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2);
2346         }
2347 }
2348
2349 void m68881_ftrap()
2350 {
2351         uint16 w2  = OPER_I_16();
2352
2353         // now check the condition
2354         if (TEST_CONDITION(w2 & 0x3f))
2355         {
2356                 // trap here
2357                 m68ki_exception_trap(EXCEPTION_TRAPV);
2358         }
2359         else    // fall through, requires eating the operand
2360         {
2361                 switch (REG_IR & 0x7)
2362                 {
2363                         case 2: // word operand
2364                                 OPER_I_16();
2365                                 break;
2366
2367                         case 3: // long word operand
2368                                 OPER_I_32();
2369                                 break;
2370
2371                         case 4: // no operand
2372                                 break;
2373                 }
2374         }
2375 }