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