]> git.sesse.net Git - pistorm/blob - m68kfpu.c
[HAX] Inline ps_read8/16/32 in emulator.c to avoid long jumps on bus transactions
[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         // For FD* and FS* prefixes we already converted the source to floatx80
1407         // so we can treat these as their parent op.
1408
1409         switch (opmode)
1410         {
1411                 case 0x44:              // FDMOVE
1412                 case 0x40:              // FSMOVE
1413                 case 0x00:              // FMOVE
1414                 {
1415                         REG_FP[dst] = source;
1416                         SET_CONDITION_CODES(REG_FP[dst]);
1417                         USE_CYCLES(4);
1418                         break;
1419                 }
1420                 case 0x01:              // FINT
1421                 {
1422                         sint32 temp;
1423                         temp = floatx80_to_int32(source, &status);
1424                         REG_FP[dst] = int32_to_floatx80(temp);
1425                         //FIXME mame doesn't use SET_CONDITION_CODES here
1426                         SET_CONDITION_CODES(REG_FP[dst]);  // JFF needs update condition codes
1427                         USE_CYCLES(4);
1428                         break;
1429                 }
1430                 case 0x02:              // FSINH
1431                 {
1432                         REG_FP[dst] = floatx80_sinh(source, &status);
1433                         SET_CONDITION_CODES(REG_FP[dst]);
1434                         USE_CYCLES(75);
1435                         break;
1436                 }
1437                 case 0x03:              // FINTRZ
1438                 {
1439                         sint32 temp;
1440                         temp = floatx80_to_int32_round_to_zero(source, &status);
1441                         REG_FP[dst] = int32_to_floatx80(temp);
1442                         //FIXME mame doesn't use SET_CONDITION_CODES here
1443                         SET_CONDITION_CODES(REG_FP[dst]);  // JFF needs update condition codes
1444                         break;
1445                 }
1446                 case 0x45:              // FDSQRT
1447                 case 0x41:              // FSSQRT
1448                 case 0x04:              // FSQRT
1449                 case 0x05:              // FSQRT
1450                 {
1451                         REG_FP[dst] = floatx80_sqrt(source, &status);
1452                         SET_CONDITION_CODES(REG_FP[dst]);
1453                         USE_CYCLES(109);
1454                         break;
1455                 }
1456                 case 0x06:      // FLOGNP1
1457                 case 0x07:      // FLOGNP1
1458                 {
1459                         REG_FP[dst] = floatx80_lognp1 (source, &status);
1460                         SET_CONDITION_CODES(REG_FP[dst]);
1461                         USE_CYCLES(594); // for MC68881
1462                         break;
1463                 }
1464                 case 0x08:      // FETOXM1
1465                 {
1466                         REG_FP[dst] = floatx80_etoxm1(source, &status);
1467                         SET_CONDITION_CODES(REG_FP[dst]);
1468                         USE_CYCLES(6);
1469                         break;
1470                 }
1471                 case 0x09:      // FTANH
1472                 {
1473                         REG_FP[dst] = floatx80_tanh(source, &status);
1474                         SET_CONDITION_CODES(REG_FP[dst]);
1475                         USE_CYCLES(75);
1476                         break;
1477                 }
1478                 case 0x0a:      // FATAN
1479                 case 0x0b:      // FATAN
1480                 {
1481                         REG_FP[dst] = floatx80_atan(source, &status);
1482                         SET_CONDITION_CODES(REG_FP[dst]);
1483                         USE_CYCLES(75);
1484                         break;
1485                 }
1486                 case 0x0c:      // FASIN
1487                 {
1488                         REG_FP[dst] = floatx80_asin(source, &status);
1489                         SET_CONDITION_CODES(REG_FP[dst]);
1490                         USE_CYCLES(75);
1491                         break;
1492                 }
1493                 case 0x0d:      // FATANH
1494                 {
1495                         REG_FP[dst] = floatx80_atanh(source, &status);
1496                         SET_CONDITION_CODES(REG_FP[dst]);
1497                         USE_CYCLES(75);
1498                         break;
1499                 }
1500                 case 0x0e:      // FSIN
1501                 {
1502                         REG_FP[dst] = floatx80_sin(source, &status);
1503                         SET_CONDITION_CODES(REG_FP[dst]);
1504                         USE_CYCLES(75);
1505                         break;
1506                 }
1507                 case 0x0f:      // FTAN
1508                 {
1509                         REG_FP[dst] = floatx80_tan(source, &status);
1510                         SET_CONDITION_CODES(REG_FP[dst]);
1511                         USE_CYCLES(75);
1512                         break;
1513                 }
1514                 case 0x10:      // FETOX
1515                 {
1516                         REG_FP[dst] = floatx80_etox(source, &status);
1517                         SET_CONDITION_CODES(REG_FP[dst]);
1518                         USE_CYCLES(75);
1519                         break;
1520                 }
1521                 case 0x11:      // FTWOTOX
1522                 {
1523                         REG_FP[dst] = floatx80_twotox(source, &status);
1524                         SET_CONDITION_CODES(REG_FP[dst]);
1525                         USE_CYCLES(75);
1526                         break;
1527                 }
1528                 case 0x12:      // FTENTOX
1529                 case 0x13:      // FTENTOX
1530                 {
1531                         REG_FP[dst] = floatx80_tentox(source, &status);
1532                         SET_CONDITION_CODES(REG_FP[dst]);
1533                         USE_CYCLES(75);
1534                         break;
1535                 }
1536                 case 0x14:      // FLOGN
1537                 {
1538                         REG_FP[dst] = floatx80_logn(source, &status);
1539                         SET_CONDITION_CODES(REG_FP[dst]);
1540                         USE_CYCLES(548); // for MC68881
1541                         break;
1542                 }
1543                 case 0x15:      // FLOG10
1544                 {
1545                         REG_FP[dst] = floatx80_log10(source, &status);
1546                         SET_CONDITION_CODES(REG_FP[dst]);
1547                         USE_CYCLES(604); // for MC68881
1548                         break;
1549                 }
1550                 case 0x16:      // FLOG2
1551                 case 0x17:      // FLOG2
1552                 {
1553                         REG_FP[dst] = floatx80_log2(source, &status);
1554                         SET_CONDITION_CODES(REG_FP[dst]);
1555                         USE_CYCLES(604); // for MC68881
1556                         break;
1557                 }
1558                 case 0x5C:              // FDABS
1559                 case 0x58:              // FSABS
1560                 case 0x18:              // FABS
1561                 {
1562                         REG_FP[dst] = source;
1563                         REG_FP[dst].high &= 0x7fff;
1564                         SET_CONDITION_CODES(REG_FP[dst]);
1565                         USE_CYCLES(3);
1566                         break;
1567                 }
1568                 case 0x19:      // FCOSH
1569                 {
1570                         REG_FP[dst] = floatx80_cosh(source, &status);
1571                         SET_CONDITION_CODES(REG_FP[dst]);
1572                         USE_CYCLES(64);
1573                         break;
1574                 }
1575                 case 0x5e:              // FDNEG
1576                 case 0x5a:              // FSNEG
1577                 case 0x1a:              // FNEG
1578                 case 0x1b:              // FNEG
1579                 {
1580                         REG_FP[dst] = source;
1581                         REG_FP[dst].high ^= 0x8000;
1582                         SET_CONDITION_CODES(REG_FP[dst]);
1583                         USE_CYCLES(3);
1584                         break;
1585                 }
1586                 case 0x1c:      // FACOS
1587                 {
1588                         REG_FP[dst] = floatx80_acos(source, &status);
1589                         SET_CONDITION_CODES(REG_FP[dst]);
1590                         USE_CYCLES(604); // for MC68881
1591                         break;
1592                         break;
1593                 }
1594                 case 0x1d:      // FCOS
1595                 {
1596                         REG_FP[dst] = floatx80_cos(source, &status);
1597                         SET_CONDITION_CODES(REG_FP[dst]);
1598                         USE_CYCLES(75);
1599                         break;
1600                 }
1601                 case 0x1e:              // FGETEXP
1602                 {
1603                         REG_FP[dst] = floatx80_getexp(source, &status);
1604                         SET_CONDITION_CODES(REG_FP[dst]);
1605                         USE_CYCLES(6);
1606                         break;
1607                 }
1608                 case 0x1f:      // FGETMAN
1609                 {
1610                         REG_FP[dst] = floatx80_getman(source, &status);
1611                         SET_CONDITION_CODES(REG_FP[dst]);
1612                         USE_CYCLES(6);
1613                         break;
1614                 }
1615                 case 0x64:              // FDDIV
1616                 case 0x60:              // FSDIV
1617                 case 0x20:              // FDIV
1618                 {
1619                         REG_FP[dst] = floatx80_div(REG_FP[dst], source, &status);
1620                         //FIXME mame doesn't use SET_CONDITION_CODES here
1621                         SET_CONDITION_CODES(REG_FP[dst]); // JFF
1622                         USE_CYCLES(43);
1623                         break;
1624                 }
1625                 case 0x21:      // FMOD
1626                 {
1627                         sint8 const mode = status.float_rounding_mode;
1628                         status.float_rounding_mode = float_round_to_zero;
1629                         uint64_t q;
1630                         flag s;
1631                         REG_FP[dst] = floatx80_rem(REG_FP[dst], source, &q, &s, &status);
1632                         SET_CONDITION_CODES(REG_FP[dst]);
1633                         status.float_rounding_mode = mode;
1634                         USE_CYCLES(43);   // guess
1635                         break;
1636                 }
1637                 case 0x66:              // FDADD
1638                 case 0x62:              // FSADD
1639                 case 0x22:              // FADD
1640                 {
1641                         REG_FP[dst] = floatx80_add(REG_FP[dst], source, &status);
1642                         SET_CONDITION_CODES(REG_FP[dst]);
1643                         USE_CYCLES(9);
1644                         break;
1645                 }
1646                 case 0x67:              // FDMUL
1647                 case 0x63:              // FSMUL
1648                 case 0x23:              // FMUL
1649                 {
1650                         REG_FP[dst] = floatx80_mul(REG_FP[dst], source, &status);
1651                         SET_CONDITION_CODES(REG_FP[dst]);
1652                         USE_CYCLES(11);
1653                         break;
1654                 }
1655                 case 0x24:      // FSGLDIV
1656                 {
1657                         REG_FP[dst] = floatx80_sgldiv(REG_FP[dst], source, &status);
1658                         USE_CYCLES(43); //  // ? (value is from FDIV)
1659                         break;
1660                 }
1661                 case 0x25:              // FREM
1662                 {
1663                         sint8 const mode = status.float_rounding_mode;
1664                         status.float_rounding_mode = float_round_nearest_even;
1665                         uint64_t q;
1666                         flag s;
1667                         REG_FP[dst] = floatx80_rem(REG_FP[dst], source, &q, &s, &status);
1668                         SET_CONDITION_CODES(REG_FP[dst]);
1669                         status.float_rounding_mode = mode;
1670                         USE_CYCLES(43); // guess
1671                         break;
1672                 }
1673                 case 0x26:      // FSCALE
1674                 {
1675                         REG_FP[dst] = floatx80_scale(REG_FP[dst], source, &status);
1676                         SET_CONDITION_CODES(REG_FP[dst]);
1677                         USE_CYCLES(46);   // (better?) guess
1678                         break;
1679                 }
1680                 case 0x27:      // FSGLMUL
1681                 {
1682                         REG_FP[dst] = floatx80_sglmul(REG_FP[dst], source, &status);
1683                         SET_CONDITION_CODES(REG_FP[dst]);
1684                         USE_CYCLES(11); // ? (value is from FMUL)
1685                         break;
1686                 }
1687                 case 0x6c:              // FDSUB
1688                 case 0x68:              // FSSUB
1689                 case 0x28:              // FSUB
1690                 case 0x29:              // FSUB
1691                 case 0x2a:              // FSUB
1692                 case 0x2b:              // FSUB
1693                 case 0x2c:              // FSUB
1694                 case 0x2d:              // FSUB
1695                 case 0x2e:              // FSUB
1696                 case 0x2f:              // FSUB
1697                 {
1698                         REG_FP[dst] = floatx80_sub(REG_FP[dst], source, &status);
1699                         SET_CONDITION_CODES(REG_FP[dst]);
1700                         USE_CYCLES(9);
1701                         break;
1702                 }
1703                 case 0x30:      // FSINCOS
1704                 case 0x31:      // FSINCOS
1705                 case 0x32:      // FSINCOS
1706                 case 0x33:      // FSINCOS
1707                 case 0x34:      // FSINCOS
1708                 case 0x35:      // FSINCOS
1709                 case 0x36:      // FSINCOS
1710                 case 0x37:      // FSINCOS
1711                 {
1712                         REG_FP[dst] = floatx80_cos(source, &status);
1713                         REG_FP[w2&7] = floatx80_sin(source, &status);
1714                         SET_CONDITION_CODES(REG_FP[dst]);
1715                         USE_CYCLES(75);
1716
1717                         break;
1718                 }
1719                 case 0x38:              // FCMP
1720                 case 0x39:              // FCMP
1721                 case 0x3c:              // FCMP
1722                 case 0x3d:              // FCMP
1723                 {
1724                         floatx80 res;
1725                         res = floatx80_sub(REG_FP[dst], source, &status);
1726                         SET_CONDITION_CODES(res);
1727                         USE_CYCLES(7);
1728                         break;
1729                 }
1730                 case 0x3a:              // FTST
1731                 case 0x3b:              // FTST
1732                 case 0x3e:              // FTST
1733                 case 0x3f:              // FTST
1734                 {
1735                         floatx80 res;
1736                         res = source;
1737                         SET_CONDITION_CODES(res);
1738                         USE_CYCLES(7);
1739                         break;
1740                 }
1741
1742                 default:        fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4);
1743         }
1744 }
1745
1746 static void fmove_reg_mem(uint16 w2)
1747 {
1748         int ea = REG_IR & 0x3f;
1749         int src = (w2 >>  7) & 0x7;
1750         int dst = (w2 >> 10) & 0x7;
1751         int k = (w2 & 0x7f);
1752
1753         switch (dst)
1754         {
1755                 case 0:         // Long-Word Integer
1756                 {
1757                         sint32 d = (sint32)floatx80_to_int32(REG_FP[src], &status);
1758                         WRITE_EA_32(ea, d);
1759                         break;
1760                 }
1761                 case 1:         // Single-precision Real
1762                 {
1763                         uint32 d = floatx80_to_float32(REG_FP[src], &status);
1764                         WRITE_EA_32(ea, d);
1765                         break;
1766                 }
1767                 case 2:         // Extended-precision Real
1768                 {
1769                         WRITE_EA_FPE(ea, REG_FP[src]);
1770                         break;
1771                 }
1772                 case 3:         // Packed-decimal Real with Static K-factor
1773                 {
1774                         // sign-extend k
1775                         k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f);
1776                         WRITE_EA_PACK(ea, k, REG_FP[src]);
1777                         break;
1778                 }
1779                 case 4:         // Word Integer
1780                 {
1781                         sint32 value = floatx80_to_int32(REG_FP[src], &status);
1782                         if (value > 0x7fff || value < -0x8000 )
1783                         {
1784                                 REG_FPSR |= FPES_OE | FPAE_IOP;
1785                         }
1786                         WRITE_EA_16(ea, (sint16)value);
1787                         break;
1788                 }
1789                 case 5:         // Double-precision Real
1790                 {
1791                         uint64 d;
1792
1793                         d = floatx80_to_float64(REG_FP[src], &status);
1794
1795                         WRITE_EA_64(ea, d);
1796                         break;
1797                 }
1798                 case 6:         // Byte Integer
1799                 {
1800                         sint32 value = floatx80_to_int32(REG_FP[src], &status);
1801                         if (value > 127 || value < -128)
1802                         {
1803                                 REG_FPSR |= FPES_OE | FPAE_IOP;
1804                         }
1805                         WRITE_EA_8(ea, (sint8)value);
1806                         break;
1807                 }
1808                 case 7:         // Packed-decimal Real with Dynamic K-factor
1809                 {
1810                         WRITE_EA_PACK(ea, REG_D[k>>4], REG_FP[src]);
1811                         break;
1812                 }
1813         }
1814
1815         USE_CYCLES(12);
1816 }
1817
1818 static void fmove_fpcr(uint16 w2)
1819 {
1820         int ea = REG_IR & 0x3f;
1821         int dir = (w2 >> 13) & 0x1;
1822         int regsel = (w2 >> 10) & 0x7;
1823         int mode = (ea >> 3) & 0x7;
1824
1825         if ((mode == 5) || (mode == 6))
1826         {
1827                 uint32 address = 0xffffffff;    // force a bus error if this doesn't get assigned
1828
1829                 if (mode == 5)
1830                 {
1831                         address = EA_AY_DI_32();
1832                 }
1833                 else if (mode == 6)
1834                 {
1835                         address = EA_AY_IX_32();
1836                 }
1837
1838                 if (dir)        // From system control reg to <ea>
1839                 {
1840                         if (regsel & 4) { m68ki_write_32(address, REG_FPCR); address += 4; }
1841                         if (regsel & 2) { m68ki_write_32(address, REG_FPSR); address += 4; }
1842                         if (regsel & 1) { m68ki_write_32(address, REG_FPIAR); address += 4; }
1843                 }
1844                 else            // From <ea> to system control reg
1845                 {
1846                         if (regsel & 4) { REG_FPCR = m68ki_read_32(address); address += 4; }
1847                         if (regsel & 2) { REG_FPSR = m68ki_read_32(address); address += 4; }
1848                         if (regsel & 1) { REG_FPIAR = m68ki_read_32(address); address += 4; }
1849                 }
1850         }
1851         else
1852         {
1853                 if (dir)    // From system control reg to <ea>
1854                 {
1855                         if (regsel & 4) WRITE_EA_32(ea, REG_FPCR);
1856                         if (regsel & 2) WRITE_EA_32(ea, REG_FPSR);
1857                         if (regsel & 1) WRITE_EA_32(ea, REG_FPIAR);
1858                 }
1859                 else        // From <ea> to system control reg
1860                 {
1861                         if (regsel & 4) REG_FPCR = READ_EA_32(ea);
1862                         if (regsel & 2) REG_FPSR = READ_EA_32(ea);
1863                         if (regsel & 1) REG_FPIAR = READ_EA_32(ea);
1864                 }
1865         }
1866
1867         // FIXME: (2011-12-18 ost)
1868         // rounding_mode and rounding_precision of softfloat.c should be set according to current fpcr
1869         // but:  with this code on Apollo the following programs in /systest/fptest will fail:
1870         // 1. Single Precision Whetstone will return wrong results never the less
1871         // 2. Vector Test will fault with 00040004: reference to illegal address
1872
1873         if ((regsel & 4) && dir == 0)
1874         {
1875                 int rnd = (REG_FPCR >> 4) & 3;
1876                 int prec = (REG_FPCR >> 6) & 3;
1877
1878 //      logerror("m68k_fpsp:fmove_fpcr fpcr=%04x prec=%d rnd=%d\n", m_fpcr, prec, rnd);
1879
1880 #ifdef FLOATX80
1881                 switch (prec)
1882                 {
1883                 case 0: // Extend (X)
1884                         status.floatx80_rounding_precision = 80;
1885                         break;
1886                 case 1: // Single (S)
1887                         status.floatx80_rounding_precision = 32;
1888                         break;
1889                 case 2: // Double (D)
1890                         status.floatx80_rounding_precision = 64;
1891                         break;
1892                 case 3: // Undefined
1893                         status.floatx80_rounding_precision = 80;
1894                         break;
1895                 }
1896 #endif
1897
1898                 switch (rnd)
1899                 {
1900                 case 0: // To Nearest (RN)
1901                         status.float_rounding_mode = float_round_nearest_even;
1902                         break;
1903                 case 1: // To Zero (RZ)
1904                         status.float_rounding_mode = float_round_to_zero;
1905                         break;
1906                 case 2: // To Minus Infinitiy (RM)
1907                         status.float_rounding_mode = float_round_down;
1908                         break;
1909                 case 3: // To Plus Infinitiy (RP)
1910                         status.float_rounding_mode = float_round_up;
1911                         break;
1912                 }
1913         }
1914
1915         USE_CYCLES(10);
1916 }
1917
1918 static void fmovem(uint16 w2)
1919 {
1920         int i;
1921         int ea = REG_IR & 0x3f;
1922         int dir = (w2 >> 13) & 0x1;
1923         int mode = (w2 >> 11) & 0x3;
1924         int reglist = w2 & 0xff;
1925
1926         uint32 mem_addr = 0;
1927         switch (ea >> 3)
1928         {
1929                 case 5:     // (d16, An)
1930                         mem_addr= EA_AY_DI_32();
1931                         break;
1932                 case 6:     // (An) + (Xn) + d8
1933                         mem_addr= EA_AY_IX_32();
1934                         break;
1935         }
1936
1937         if (dir)        // From FP regs to mem
1938         {
1939                 switch (mode)
1940                 {
1941                         case 1: // Dynamic register list, postincrement or control addressing mode.
1942                                 // FIXME: not really tested, but seems to work
1943                                 reglist = REG_D[(reglist >> 4) & 7];
1944                                 /* fall through */
1945                                 /* no break */
1946                         case 0:     // Static register list, predecrement or control addressing mode
1947                         {
1948                                 for (i=0; i < 8; i++)
1949                                 {
1950                                         if (reglist & (1 << i))
1951                                         {
1952                                                 switch (ea >> 3)
1953                                                 {
1954                                                         case 5:     // (d16, An)
1955                                                         case 6:     // (An) + (Xn) + d8
1956                                                                 store_extended_float80(mem_addr, REG_FP[i]);
1957                                                                 mem_addr += 12;
1958                                                                 break;
1959                                                         default:
1960                                                                 WRITE_EA_FPE(ea, REG_FP[i]);
1961                                                                 break;
1962                                                 }
1963
1964                                                 USE_CYCLES(2);
1965                                         }
1966                                 }
1967                                 break;
1968                         }
1969
1970                         case 2:         // Static register list, postdecrement or control addressing mode.     
1971                         {
1972                                 for (i=0; i < 8; i++)
1973                                 {
1974                                         if (reglist & (1 << i))
1975                                         {
1976                                                 switch (ea >> 3)
1977                                                 {
1978                                                         case 5:     // (d16, An)
1979                                                         case 6:     // (An) + (Xn) + d8
1980                                                                 store_extended_float80(mem_addr, REG_FP[7-i]);
1981                                                                 mem_addr += 12;
1982                                                                 break;
1983                                                         default:
1984                                                                 WRITE_EA_FPE(ea, REG_FP[7-i]);
1985                                                                 break;
1986                                                 }
1987
1988                                                 USE_CYCLES(2);
1989                                         }
1990                                 }
1991                                 break;
1992                         }
1993
1994                         default:        fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
1995                 }
1996         }
1997         else            // From mem to FP regs
1998         {
1999                 switch (mode)
2000                 {
2001                         case 3: // Dynamic register list, predecrement addressing mode.
2002                                 // FIXME: not really tested, but seems to work
2003                                 reglist = REG_D[(reglist >> 4) & 7];
2004                                 /* fall through */
2005                                 /* no break */
2006                         case 2:         // Static register list, postincrement or control addressing mode
2007                         {
2008                                 for (i=0; i < 8; i++)
2009                                 {
2010                                         if (reglist & (1 << i))
2011                                         {
2012                                                 switch (ea >> 3)
2013                                                 {
2014                                                         case 5:     // (d16, An)
2015                                                         case 6:     // (An) + (Xn) + d8
2016                                                                 REG_FP[7-i] = load_extended_float80(mem_addr);
2017                                                                 mem_addr += 12;
2018                                                                 break;
2019                                                         default:
2020                                                                 REG_FP[7-i] = READ_EA_FPE(ea);
2021                                                                 break;
2022                                                 }
2023                                                 USE_CYCLES(2);
2024                                         }
2025                                 }
2026                                 break;
2027                         }
2028
2029                         default:        fatalerror("M680x0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
2030                 }
2031         }
2032 }
2033
2034 static void fscc()
2035 {
2036         int ea = REG_IR & 0x3f;
2037         int condition = (sint16)(OPER_I_16());
2038
2039         WRITE_EA_8(ea, TEST_CONDITION(condition) ? 0xff : 0);
2040         USE_CYCLES(7);  // ???
2041 }
2042 static void fbcc16(void)
2043 {
2044         sint32 offset;
2045         int condition = REG_IR & 0x3f;
2046
2047         offset = (sint16)(OPER_I_16());
2048
2049         // TODO: condition and jump!!!
2050         if (TEST_CONDITION(condition))
2051         {
2052                 m68ki_trace_t0();                          /* auto-disable (see m68kcpu.h) */
2053                 m68ki_branch_16(offset-2);
2054         }
2055
2056         USE_CYCLES(7);
2057 }
2058
2059 static void fbcc32(void)
2060 {
2061         sint32 offset;
2062         int condition = REG_IR & 0x3f;
2063
2064         offset = OPER_I_32();
2065
2066         // TODO: condition and jump!!!
2067         if (TEST_CONDITION(condition))
2068         {
2069                 m68ki_trace_t0();                          /* auto-disable (see m68kcpu.h) */
2070                 m68ki_branch_32(offset-4);
2071         }
2072
2073         USE_CYCLES(7);
2074 }
2075
2076
2077 void m68040_fpu_op0()
2078 {
2079         m68ki_cpu.fpu_just_reset = 0;
2080
2081         switch ((REG_IR >> 6) & 0x3)
2082         {
2083                 case 0:
2084                 {
2085                         uint16 w2 = OPER_I_16();
2086                         switch ((w2 >> 13) & 0x7)
2087                         {
2088                                 case 0x0:       // FPU ALU FP, FP
2089                                 case 0x2:       // FPU ALU ea, FP
2090                                 {
2091                                         fpgen_rm_reg(w2);
2092                                         break;
2093                                 }
2094
2095                                 case 0x3:       // FMOVE FP, ea
2096                                 {
2097                                         fmove_reg_mem(w2);
2098                                         break;
2099                                 }
2100
2101                                 case 0x4:       // FMOVEM ea, FPCR
2102                                 case 0x5:       // FMOVEM FPCR, ea
2103                                 {
2104                                         fmove_fpcr(w2);
2105                                         break;
2106                                 }
2107
2108                                 case 0x6:       // FMOVEM ea, list
2109                                 case 0x7:       // FMOVEM list, ea
2110                                 {
2111                                         fmovem(w2);
2112                                         break;
2113                                 }
2114
2115                                 default:        fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4);
2116                         }
2117                         break;
2118                 }
2119
2120                 case 1:           // FBcc disp16
2121                 {
2122                         switch ((REG_IR >> 3) & 0x7) {
2123                         case 1: // FDBcc
2124                                 // TODO:
2125                                 printf("M68kFPU: unimplemented FDBcc main op %d with mode %d at %08X\n", (REG_IR >> 6) & 0x3, (REG_IR >> 3) & 0x7, REG_PC-4);
2126                                 break;
2127                         default: // FScc (?)
2128                                 fscc();
2129                                 return;
2130                         }
2131                         fatalerror("M68kFPU: unimplemented main op %d with mode %d at %08X\n", (REG_IR >> 6) & 0x3, (REG_IR >> 3) & 0x7, REG_PC-4);
2132                         break;
2133                 }
2134                 case 2:     // FBcc disp16
2135                 {
2136                         fbcc16();
2137                         break;
2138                 }
2139                 case 3:     // FBcc disp32
2140                 {
2141                         fbcc32();
2142                         break;
2143                 }
2144
2145                 default:    fatalerror("M68kFPU: unimplemented main op %d\n", (REG_IR >> 6) & 0x3);
2146         }
2147 }
2148
2149 static int perform_fsave(uint32 addr, int inc)
2150 {
2151         if(m68ki_cpu.cpu_type & CPU_TYPE_040)
2152         {
2153                 if(inc)
2154                 {
2155                         m68ki_write_32(addr, 0x41000000);
2156                         return 4 -4;
2157                 }
2158                 else
2159                 {
2160                         m68ki_write_32(addr, 0x41000000);
2161                         return -4 +4;
2162                 }
2163         }
2164
2165         if (inc)
2166         {
2167                 // 68881 IDLE, version 0x1f
2168                 m68ki_write_32(addr, 0x1f180000);
2169                 m68ki_write_32(addr+4, 0);
2170                 m68ki_write_32(addr+8, 0);
2171                 m68ki_write_32(addr+12, 0);
2172                 m68ki_write_32(addr+16, 0);
2173                 m68ki_write_32(addr+20, 0);
2174                 m68ki_write_32(addr+24, 0x70000000);
2175                 return 7*4 -4;
2176         }
2177         else
2178         {
2179                 m68ki_write_32(addr+4-4, 0x70000000);
2180                 m68ki_write_32(addr+4-8, 0);
2181                 m68ki_write_32(addr+4-12, 0);
2182                 m68ki_write_32(addr+4-16, 0);
2183                 m68ki_write_32(addr+4-20, 0);
2184                 m68ki_write_32(addr+4-24, 0);
2185                 m68ki_write_32(addr+4-28, 0x1f180000);
2186                 return -7*4 +4;
2187         }
2188 }
2189
2190 // FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0
2191 static void do_frestore_null(void)
2192 {
2193         int i;
2194
2195         REG_FPCR = 0;
2196         REG_FPSR = 0;
2197         REG_FPIAR = 0;
2198         for (i = 0; i < 8; i++)
2199         {
2200                 REG_FP[i].high = 0x7fff;
2201                 REG_FP[i].low = U64(0xffffffffffffffff);
2202         }
2203
2204         // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL
2205         // The PRM says it's possible to generate a NULL frame, but not how/when/why.  (need the 68881/68882 manual!)
2206         m68ki_cpu.fpu_just_reset = 1;
2207 }
2208
2209 void m68040_do_fsave(uint32 addr, int reg, int inc)
2210 {
2211         if (m68ki_cpu.fpu_just_reset)
2212         {
2213                 m68ki_write_32(addr, 0);
2214         }
2215         else
2216         {
2217                 // we normally generate an IDLE frame
2218                 int delta = perform_fsave(addr, inc);
2219                 if(reg != -1)
2220                         REG_A[reg] += delta;
2221         }
2222 }
2223
2224 void m68040_do_frestore(uint32 addr, int reg)
2225 {
2226         uint32 temp = m68ki_read_32(addr);
2227         // check for nullptr frame
2228         if (temp & 0xff000000)
2229         {
2230                 // we don't handle non-nullptr frames
2231                 m68ki_cpu.fpu_just_reset = 0;
2232
2233                 if (reg != -1)
2234                 {
2235                         uint8 m40 = !!(m68ki_cpu.cpu_type & CPU_TYPE_040);
2236                         // how about an IDLE frame?
2237                         if (!m40 && ((temp & 0x00ff0000) == 0x00180000))
2238                         {
2239                                 REG_A[reg] += 7*4-4;
2240                         }
2241                         else if (m40 && ((temp & 0xffff0000) == 0x41000000))
2242                         {
2243 //                              REG_A[reg] += 4;
2244                         } // check UNIMP
2245                         else if ((temp & 0x00ff0000) == 0x00380000)
2246                         {
2247                                 REG_A[reg] += 14*4;
2248                         } // check BUSY
2249                         else if ((temp & 0x00ff0000) == 0x00b40000)
2250                         {
2251                                 REG_A[reg] += 45*4;
2252                         }
2253                 }
2254         }
2255         else
2256         {
2257                 do_frestore_null();
2258         }
2259 }
2260
2261 void m68040_fpu_op1()
2262 {
2263         int ea = REG_IR & 0x3f;
2264         int mode = (ea >> 3) & 0x7;
2265         int reg = (ea & 0x7);
2266         uint32 addr;
2267
2268         switch ((REG_IR >> 6) & 0x3)
2269         {
2270                 case 0:         // FSAVE <ea>
2271                 {
2272                         switch (mode)
2273                         {
2274                                 case 2: // (An)
2275                                         addr = REG_A[reg];
2276                                         m68040_do_fsave(addr, -1, 1);
2277                                         break;
2278
2279                                 case 3: // (An)+
2280                                         addr = EA_AY_PI_32();
2281                                         printf("FSAVE mode %d, reg A%d=0x%08x\n",mode,reg,REG_A[reg]);
2282                                         m68040_do_fsave(addr, -1, 1); // FIXME: -1 was reg
2283                                         break;
2284
2285                                 case 4: // -(An)
2286                                         addr = EA_AY_PD_32();
2287                                         m68040_do_fsave(addr, reg, 0); // FIXME: -1 was reg
2288                                         break;
2289                                 case 5: // (D16, An)
2290                                         addr = EA_AY_DI_16();
2291                                         m68040_do_fsave(addr, -1, 1);
2292                                         break;
2293
2294                                 case 6: // (An) + (Xn) + d8
2295                                         addr = EA_AY_IX_16();
2296                                         m68040_do_fsave(addr, -1, 1);
2297                                         break;
2298
2299                                 case 7: //
2300                                 {
2301                                         switch (reg)
2302                                         {
2303                                                 case 1:     // (abs32)
2304                                                 {
2305                                                         addr = EA_AL_32();
2306                                                         m68040_do_fsave(addr, -1, 1);
2307                                                         break;
2308                                                 }
2309                                                 case 2:     // (d16, PC)
2310                                                 {
2311                                                         addr = EA_PCDI_16();
2312                                                         m68040_do_fsave(addr, -1, 1);
2313                                                         break;
2314                                                 }
2315                                                 default:
2316                                                         fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2317                                         }
2318                                 }
2319                                 break;
2320
2321                                 default:
2322                                         fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2323                         }
2324                 }
2325                 break;
2326
2327                 case 1:         // FRESTORE <ea>
2328                 {
2329                         switch (mode)
2330                         {
2331                                 case 2: // (An)
2332                                         addr = REG_A[reg];
2333                                         m68040_do_frestore(addr, -1);
2334                                         break;
2335
2336                                 case 3: // (An)+
2337                                         addr = EA_AY_PI_32();
2338                                         m68040_do_frestore(addr, reg);
2339                                         break;
2340
2341                                 case 5: // (D16, An)
2342                                         addr = EA_AY_DI_16();
2343                                         m68040_do_frestore(addr, -1);
2344                                         break;
2345
2346                                 case 6: // (An) + (Xn) + d8
2347                                         addr = EA_AY_IX_16();
2348                                         m68040_do_frestore(addr, -1);
2349                                         break;
2350
2351                                 case 7: //
2352                                 {
2353                                         switch (reg)
2354                                         {
2355                                                 case 1:     // (abs32)
2356                                                 {
2357                                                         addr = EA_AL_32();
2358                                                         m68040_do_frestore(addr, -1);
2359                                                         break;
2360                                                 }
2361                                                 case 2:     // (d16, PC)
2362                                                 {
2363                                                         addr = EA_PCDI_16();
2364                                                         m68040_do_frestore(addr, -1);
2365                                                         break;
2366                                                 }
2367                                                 default:
2368                                                         fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2369                                         }
2370                                 }
2371                                 break;
2372
2373                                 default:
2374                                         fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC);
2375                         }
2376                 }
2377                 break;
2378
2379                 default:    fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2);
2380         }
2381 }
2382
2383 void m68881_ftrap()
2384 {
2385         uint16 w2  = OPER_I_16();
2386
2387         // now check the condition
2388         if (TEST_CONDITION(w2 & 0x3f))
2389         {
2390                 // trap here
2391                 m68ki_exception_trap(EXCEPTION_TRAPV);
2392         }
2393         else    // fall through, requires eating the operand
2394         {
2395                 switch (REG_IR & 0x7)
2396                 {
2397                         case 2: // word operand
2398                                 OPER_I_16();
2399                                 break;
2400
2401                         case 3: // long word operand
2402                                 OPER_I_32();
2403                                 break;
2404
2405                         case 4: // no operand
2406                                 break;
2407                 }
2408         }
2409 }