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