1 #define fatalerror printf
2
3 #define FPCC_N 0x08000000
4 #define FPCC_Z 0x04000000
5 #define FPCC_I 0x02000000
6 #define FPCC_NAN 0x01000000
7
8 #define DOUBLE_INFINITY U64(0x7ff0000000000000)
9 #define DOUBLE_EXPONENT U64(0x7ff0000000000000)
10 #define DOUBLE_MANTISSA U64(0x000fffffffffffff)
11
SET_CONDITION_CODES(fp_reg reg)12 INLINE void SET_CONDITION_CODES(fp_reg reg)
13 {
14 REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN);
15
16 // sign flag
17 if (reg.i & U64(0x8000000000000000))
18 {
19 REG_FPSR |= FPCC_N;
20 }
21
22 // zero flag
23 if ((reg.i & U64(0x7fffffffffffffff)) == 0)
24 {
25 REG_FPSR |= FPCC_Z;
26 }
27
28 // infinity flag
29 if ((reg.i & U64(0x7fffffffffffffff)) == DOUBLE_INFINITY)
30 {
31 REG_FPSR |= FPCC_I;
32 }
33
34 // NaN flag
35 if (((reg.i & DOUBLE_EXPONENT) == DOUBLE_EXPONENT) && ((reg.i & DOUBLE_MANTISSA) != 0))
36 {
37 REG_FPSR |= FPCC_NAN;
38 }
39 }
40
TEST_CONDITION(int condition)41 INLINE int TEST_CONDITION(int condition)
42 {
43 int n = (REG_FPSR & FPCC_N) != 0;
44 int z = (REG_FPSR & FPCC_Z) != 0;
45 int nan = (REG_FPSR & FPCC_NAN) != 0;
46 int r = 0;
47 switch (condition)
48 {
49 case 0x00: return 0; // False
50 case 0x01: return (z); // Equal
51 case 0x0e: return (!z); // Not Equal
52 case 0x0f: return 1; // True
53 case 0x12: return (!(nan || z || n)); // Greater Than
54 case 0x13: return (z || !(nan || n)); // Greater or Equal
55 case 0x14: return (n && !(nan || z)); // Less Than
56 case 0x15: return (z || (n && !nan)); // Less Than or Equal
57 case 0x1a: return (nan || !(n || z)); // Not Less Than or Equal
58 case 0x1b: return (nan || z || !n); // Not Less Than
59 case 0x1c: return (nan || (n && !z)); // Not Greater or Equal Than
60 case 0x1d: return (nan || z || n); // Not Greater Than
61
62 default: fatalerror("M68040: test_condition: unhandled condition %02X\n", condition);
63 }
64
65 return r;
66 }
67
READ_EA_8(int ea)68 static UINT8 READ_EA_8(int ea)
69 {
70 int mode = (ea >> 3) & 0x7;
71 int reg = (ea & 0x7);
72
73 switch (mode)
74 {
75 case 0: // Dn
76 {
77 return REG_D[reg];
78 }
79 case 5: // (d16, An)
80 {
81 UINT32 ea = EA_AY_DI_8();
82 return m68ki_read_8(ea);
83 }
84 case 6: // (An) + (Xn) + d8
85 {
86 UINT32 ea = EA_AY_IX_8();
87 return m68ki_read_8(ea);
88 }
89 case 7:
90 {
91 switch (reg)
92 {
93 case 1: // (xxx).L
94 {
95 UINT32 d1 = OPER_I_16();
96 UINT32 d2 = OPER_I_16();
97 UINT32 ea = (d1 << 16) | d2;
98 return m68ki_read_8(ea);
99 }
100 case 4: // #<data>
101 {
102 return OPER_I_8();
103 }
104 default: fatalerror("MC68040: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
105 }
106 break;
107 }
108 default: fatalerror("MC68040: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
109 }
110
111 return 0;
112 }
113
READ_EA_16(int ea)114 static UINT16 READ_EA_16(int ea)
115 {
116 int mode = (ea >> 3) & 0x7;
117 int reg = (ea & 0x7);
118
119 switch (mode)
120 {
121 case 0: // Dn
122 {
123 return (UINT16)(REG_D[reg]);
124 }
125 case 2: // (An)
126 {
127 UINT32 ea = REG_A[reg];
128 return m68ki_read_16(ea);
129 }
130 case 5: // (d16, An)
131 {
132 UINT32 ea = EA_AY_DI_16();
133 return m68ki_read_16(ea);
134 }
135 case 6: // (An) + (Xn) + d8
136 {
137 UINT32 ea = EA_AY_IX_16();
138 return m68ki_read_16(ea);
139 }
140 case 7:
141 {
142 switch (reg)
143 {
144 case 1: // (xxx).L
145 {
146 UINT32 d1 = OPER_I_16();
147 UINT32 d2 = OPER_I_16();
148 UINT32 ea = (d1 << 16) | d2;
149 return m68ki_read_16(ea);
150 }
151 case 4: // #<data>
152 {
153 return OPER_I_16();
154 }
155
156 default: fatalerror("MC68040: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
157 }
158 break;
159 }
160 default: fatalerror("MC68040: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
161 }
162
163 return 0;
164 }
165
READ_EA_32(int ea)166 static UINT32 READ_EA_32(int ea)
167 {
168 int mode = (ea >> 3) & 0x7;
169 int reg = (ea & 0x7);
170
171 switch (mode)
172 {
173 case 0: // Dn
174 {
175 return REG_D[reg];
176 }
177 case 2: // (An)
178 {
179 UINT32 ea = REG_A[reg];
180 return m68ki_read_32(ea);
181 }
182 case 3: // (An)+
183 {
184 UINT32 ea = EA_AY_PI_32();
185 return m68ki_read_32(ea);
186 }
187 case 5: // (d16, An)
188 {
189 UINT32 ea = EA_AY_DI_32();
190 return m68ki_read_32(ea);
191 }
192 case 6: // (An) + (Xn) + d8
193 {
194 UINT32 ea = EA_AY_IX_32();
195 return m68ki_read_32(ea);
196 }
197 case 7:
198 {
199 switch (reg)
200 {
201 case 1: // (xxx).L
202 {
203 UINT32 d1 = OPER_I_16();
204 UINT32 d2 = OPER_I_16();
205 UINT32 ea = (d1 << 16) | d2;
206 return m68ki_read_32(ea);
207 }
208 case 2: // (d16, PC)
209 {
210 UINT32 ea = EA_PCDI_32();
211 return m68ki_read_32(ea);
212 }
213 case 4: // #<data>
214 {
215 return OPER_I_32();
216 }
217 default: fatalerror("MC68040: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
218 }
219 break;
220 }
221 default: fatalerror("MC68040: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
222 }
223 return 0;
224 }
225
WRITE_EA_32(int ea,UINT32 data)226 static void WRITE_EA_32(int ea, UINT32 data)
227 {
228 int mode = (ea >> 3) & 0x7;
229 int reg = (ea & 0x7);
230
231 switch (mode)
232 {
233 case 0: // Dn
234 {
235 REG_D[reg] = data;
236 break;
237 }
238 case 2: // (An)
239 {
240 UINT32 ea = REG_A[reg];
241 m68ki_write_32(ea, data);
242 break;
243 }
244 case 3: // (An)+
245 {
246 UINT32 ea = EA_AY_PI_32();
247 m68ki_write_32(ea, data);
248 break;
249 }
250 case 4: // -(An)
251 {
252 UINT32 ea = EA_AY_PD_32();
253 m68ki_write_32(ea, data);
254 break;
255 }
256 case 5: // (d16, An)
257 {
258 UINT32 ea = EA_AY_DI_32();
259 m68ki_write_32(ea, data);
260 break;
261 }
262 case 6: // (An) + (Xn) + d8
263 {
264 UINT32 ea = EA_AY_IX_32();
265 m68ki_write_32(ea, data);
266 break;
267 }
268 case 7:
269 {
270 switch (reg)
271 {
272 case 1: // (xxx).L
273 {
274 UINT32 d1 = OPER_I_16();
275 UINT32 d2 = OPER_I_16();
276 UINT32 ea = (d1 << 16) | d2;
277 m68ki_write_32(ea, data);
278 break;
279 }
280 case 2: // (d16, PC)
281 {
282 UINT32 ea = EA_PCDI_32();
283 m68ki_write_32(ea, data);
284 break;
285 }
286 default: fatalerror("MC68040: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
287 }
288 break;
289 }
290 default: fatalerror("MC68040: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC);
291 }
292 }
293
READ_EA_64(int ea)294 static UINT64 READ_EA_64(int ea)
295 {
296 int mode = (ea >> 3) & 0x7;
297 int reg = (ea & 0x7);
298 UINT32 h1, h2;
299
300 switch (mode)
301 {
302 case 2: // (An)
303 {
304 UINT32 ea = REG_A[reg];
305 h1 = m68ki_read_32(ea+0);
306 h2 = m68ki_read_32(ea+4);
307 return (UINT64)(h1) << 32 | (UINT64)(h2);
308 }
309 case 3: // (An)+
310 {
311 UINT32 ea = REG_A[reg];
312 REG_A[reg] += 8;
313 h1 = m68ki_read_32(ea+0);
314 h2 = m68ki_read_32(ea+4);
315 return (UINT64)(h1) << 32 | (UINT64)(h2);
316 }
317 case 5: // (d16, An)
318 {
319 UINT32 ea = EA_AY_DI_32();
320 h1 = m68ki_read_32(ea+0);
321 h2 = m68ki_read_32(ea+4);
322 return (UINT64)(h1) << 32 | (UINT64)(h2);
323 }
324 case 7:
325 {
326 switch (reg)
327 {
328 case 4: // #<data>
329 {
330 h1 = OPER_I_32();
331 h2 = OPER_I_32();
332 return (UINT64)(h1) << 32 | (UINT64)(h2);
333 }
334 case 2: // (d16, PC)
335 {
336 UINT32 ea = EA_PCDI_32();
337 h1 = m68ki_read_32(ea+0);
338 h2 = m68ki_read_32(ea+4);
339 return (UINT64)(h1) << 32 | (UINT64)(h2);
340 }
341 default: fatalerror("MC68040: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
342 }
343 break;
344 }
345 default: fatalerror("MC68040: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC);
346 }
347
348 return 0;
349 }
350
WRITE_EA_64(int ea,UINT64 data)351 static void WRITE_EA_64(int ea, UINT64 data)
352 {
353 int mode = (ea >> 3) & 0x7;
354 int reg = (ea & 0x7);
355
356 switch (mode)
357 {
358 case 2: // (An)
359 {
360 UINT32 ea = REG_A[reg];
361 m68ki_write_32(ea, (UINT32)(data >> 32));
362 m68ki_write_32(ea, (UINT32)(data));
363 break;
364 }
365 case 4: // -(An)
366 {
367 UINT32 ea;
368 REG_A[reg] -= 8;
369 ea = REG_A[reg];
370 m68ki_write_32(ea+0, (UINT32)(data >> 32));
371 m68ki_write_32(ea+4, (UINT32)(data));
372 break;
373 }
374 case 5: // (d16, An)
375 {
376 UINT32 ea = EA_AY_DI_32();
377 m68ki_write_32(ea+0, (UINT32)(data >> 32));
378 m68ki_write_32(ea+4, (UINT32)(data));
379 break;
380 }
381 default: fatalerror("MC68040: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (UINT32)(data >> 32), (UINT32)(data), REG_PC);
382 }
383 }
384
READ_EA_FPE(int ea)385 static fp_reg READ_EA_FPE(int ea)
386 {
387 fp_reg r;
388 int mode = (ea >> 3) & 0x7;
389 int reg = (ea & 0x7);
390
391 // TODO: convert to extended floating-point!
392
393 switch (mode)
394 {
395 case 3: // (An)+
396 {
397 UINT32 d1,d2,d3;
398 UINT32 ea = REG_A[reg];
399 REG_A[reg] += 12;
400 d1 = m68ki_read_32(ea+0);
401 d2 = m68ki_read_32(ea+4);
402 d3 = m68ki_read_32(ea+8);
403 r.i = (UINT64)(d1) << 32 | (UINT64)(d2);
404 break;
405 }
406 default: fatalerror("MC68040: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC);
407 }
408
409 return r;
410 }
411
WRITE_EA_FPE(int ea,fp_reg fpr)412 static void WRITE_EA_FPE(int ea, fp_reg fpr)
413 {
414 int mode = (ea >> 3) & 0x7;
415 int reg = (ea & 0x7);
416
417 // TODO: convert to extended floating-point!
418
419 switch (mode)
420 {
421 case 4: // -(An)
422 {
423 UINT32 ea;
424 REG_A[reg] -= 12;
425 ea = REG_A[reg];
426 m68ki_write_32(ea+0, (UINT32)((UINT64)fpr.i >> 32));
427 m68ki_write_32(ea+4, (UINT32)(fpr.i));
428 m68ki_write_32(ea+8, 0);
429 break;
430 }
431 default: fatalerror("MC68040: WRITE_EA_FPE: unhandled mode %d, reg %d, data %f at %08X\n", mode, reg, fpr.f, REG_PC);
432 }
433 }
434
435
fpgen_rm_reg(UINT16 w2)436 static void fpgen_rm_reg(UINT16 w2)
437 {
438 int ea = REG_IR & 0x3f;
439 int rm = (w2 >> 14) & 0x1;
440 int src = (w2 >> 10) & 0x7;
441 int dst = (w2 >> 7) & 0x7;
442 int opmode = w2 & 0x7f;
443 double source;
444
445 if (rm)
446 {
447 switch (src)
448 {
449 case 0: // Long-Word Integer
450 {
451 INT32 d = READ_EA_32(ea);
452 source = (double)(d);
453 break;
454 }
455 case 1: // Single-precision Real
456 {
457 UINT32 d = READ_EA_32(ea);
458 source = (double)(*(float*)&d);
459 break;
460 }
461 case 2: // Extended-precision Real
462 {
463 fatalerror("fpgen_rm_reg: extended-precision real load unimplemented at %08X\n", REG_PC-4);
464 break;
465 }
466 case 3: // Packed-decimal Real
467 {
468 fatalerror("fpgen_rm_reg: packed-decimal real load unimplemented at %08X\n", REG_PC-4);
469 break;
470 }
471 case 4: // Word Integer
472 {
473 INT16 d = READ_EA_16(ea);
474 source = (double)(d);
475 break;
476 }
477 case 5: // Double-precision Real
478 {
479 UINT64 d = READ_EA_64(ea);
480 source = *(double*)&d;
481 break;
482 }
483 case 6: // Byte Integer
484 {
485 INT8 d = READ_EA_8(ea);
486 source = (double)(d);
487 break;
488 }
489 default: fatalerror("fmove_rm_reg: invalid source specifier at %08X\n", REG_PC-4);
490 }
491 }
492 else
493 {
494 source = REG_FP[src].f;
495 }
496
497 switch (opmode)
498 {
499 case 0x00: // FMOVE
500 {
501 REG_FP[dst].f = source;
502 USE_CYCLES(4);
503 break;
504 }
505 case 0x04: // FSQRT
506 {
507 REG_FP[dst].f = sqrt(source);
508 SET_CONDITION_CODES(REG_FP[dst]);
509 USE_CYCLES(109);
510 break;
511 }
512 case 0x18: // FABS
513 {
514 REG_FP[dst].f = fabs(source);
515 SET_CONDITION_CODES(REG_FP[dst]);
516 USE_CYCLES(3);
517 break;
518 }
519 case 0x1a: // FNEG
520 {
521 REG_FP[dst].f = -source;
522 SET_CONDITION_CODES(REG_FP[dst]);
523 USE_CYCLES(3);
524 break;
525 }
526 case 0x20: // FDIV
527 {
528 REG_FP[dst].f /= source;
529 USE_CYCLES(43);
530 break;
531 }
532 case 0x22: // FADD
533 {
534 REG_FP[dst].f += source;
535 SET_CONDITION_CODES(REG_FP[dst]);
536 USE_CYCLES(9);
537 break;
538 }
539 case 0x23: // FMUL
540 {
541 REG_FP[dst].f *= source;
542 SET_CONDITION_CODES(REG_FP[dst]);
543 USE_CYCLES(11);
544 break;
545 }
546 case 0x28: // FSUB
547 {
548 REG_FP[dst].f -= source;
549 SET_CONDITION_CODES(REG_FP[dst]);
550 USE_CYCLES(9);
551 break;
552 }
553 case 0x38: // FCMP
554 {
555 fp_reg res;
556 res.f = REG_FP[dst].f - source;
557 SET_CONDITION_CODES(res);
558 USE_CYCLES(7);
559 break;
560 }
561 case 0x3a: // FTST
562 {
563 fp_reg res;
564 res.f = source;
565 SET_CONDITION_CODES(res);
566 USE_CYCLES(7);
567 break;
568 }
569
570 default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4);
571 }
572 }
573
fmove_reg_mem(UINT16 w2)574 static void fmove_reg_mem(UINT16 w2)
575 {
576 int ea = REG_IR & 0x3f;
577 int src = (w2 >> 7) & 0x7;
578 int dst = (w2 >> 10) & 0x7;
579 //int kfactor = w2 & 0x7f;
580
581 switch (dst)
582 {
583 case 0: // Long-Word Integer
584 {
585 INT32 d = (INT32)(REG_FP[src].f);
586 WRITE_EA_32(ea, d);
587 break;
588 }
589 case 1: // Single-precision Real
590 {
591 float f = (float)(REG_FP[src].f);
592 UINT32 d = *(UINT32 *)&f;
593 WRITE_EA_32(ea, d);
594 break;
595 }
596 case 2: // Extended-precision Real
597 {
598 fatalerror("fmove_reg_mem: extended-precision real store unimplemented at %08X\n", REG_PC-4);
599 break;
600 }
601 case 3: // Packed-decimal Real with Static K-factor
602 {
603 fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4);
604 break;
605 }
606 case 4: // Word Integer
607 {
608 fatalerror("fmove_reg_mem: word integer store unimplemented at %08X\n", REG_PC-4);
609 break;
610 }
611 case 5: // Double-precision Real
612 {
613 UINT64 d = REG_FP[src].i;
614 WRITE_EA_64(ea, d);
615 break;
616 }
617 case 6: // Byte Integer
618 {
619 fatalerror("fmove_reg_mem: byte integer store unimplemented at %08X\n", REG_PC-4);
620 break;
621 }
622 case 7: // Packed-decimal Real with Dynamic K-factor
623 {
624 fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4);
625 break;
626 }
627 }
628
629 USE_CYCLES(12);
630 }
631
fmove_fpcr(UINT16 w2)632 static void fmove_fpcr(UINT16 w2)
633 {
634 int ea = REG_IR & 0x3f;
635 int dir = (w2 >> 13) & 0x1;
636 int reg = (w2 >> 10) & 0x7;
637
638 if (dir) // From system control reg to <ea>
639 {
640 switch (reg)
641 {
642 case 1: WRITE_EA_32(ea, REG_FPIAR); break;
643 case 2: WRITE_EA_32(ea, REG_FPSR); break;
644 case 4: WRITE_EA_32(ea, REG_FPCR); break;
645 default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir);
646 }
647 }
648 else // From <ea> to system control reg
649 {
650 switch (reg)
651 {
652 case 1: REG_FPIAR = READ_EA_32(ea); break;
653 case 2: REG_FPSR = READ_EA_32(ea); break;
654 case 4: REG_FPCR = READ_EA_32(ea); break;
655 default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir);
656 }
657 }
658
659 USE_CYCLES(10);
660 }
661
fmovem(UINT16 w2)662 static void fmovem(UINT16 w2)
663 {
664 int i;
665 int ea = REG_IR & 0x3f;
666 int dir = (w2 >> 13) & 0x1;
667 int mode = (w2 >> 11) & 0x3;
668 int reglist = w2 & 0xff;
669
670 if (dir) // From FP regs to mem
671 {
672 switch (mode)
673 {
674 case 0: // Static register list, predecrement addressing mode
675 {
676 for (i=0; i < 8; i++)
677 {
678 if (reglist & (1 << i))
679 {
680 WRITE_EA_FPE(ea, REG_FP[i]);
681 USE_CYCLES(2);
682 }
683 }
684 break;
685 }
686
687 default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
688 }
689 }
690 else // From mem to FP regs
691 {
692 switch (mode)
693 {
694 case 2: // Static register list, postincrement addressing mode
695 {
696 for (i=0; i < 8; i++)
697 {
698 if (reglist & (1 << i))
699 {
700 REG_FP[7-i] = READ_EA_FPE(ea);
701 USE_CYCLES(2);
702 }
703 }
704 break;
705 }
706
707 default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4);
708 }
709 }
710 }
711
fbcc16(void)712 static void fbcc16(void)
713 {
714 INT32 offset;
715 int condition = REG_IR & 0x3f;
716
717 offset = (INT16)(OPER_I_16());
718
719 // TODO: condition and jump!!!
720 if (TEST_CONDITION(condition))
721 {
722 m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
723 m68ki_branch_16(offset-2);
724 }
725
726 USE_CYCLES(7);
727 }
728
fbcc32(void)729 static void fbcc32(void)
730 {
731 INT32 offset;
732 int condition = REG_IR & 0x3f;
733
734 offset = OPER_I_32();
735
736 // TODO: condition and jump!!!
737 if (TEST_CONDITION(condition))
738 {
739 m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
740 m68ki_branch_32(offset-4);
741 }
742
743 USE_CYCLES(7);
744 }
745
746
m68040_fpu_op0(void)747 void m68040_fpu_op0(void)
748 {
749 switch ((REG_IR >> 6) & 0x3)
750 {
751 case 0:
752 {
753 UINT16 w2 = OPER_I_16();
754 switch ((w2 >> 13) & 0x7)
755 {
756 case 0x0: // FPU ALU FP, FP
757 case 0x2: // FPU ALU ea, FP
758 {
759 fpgen_rm_reg(w2);
760 break;
761 }
762
763 case 0x3: // FMOVE FP, ea
764 {
765 fmove_reg_mem(w2);
766 break;
767 }
768
769 case 0x4: // FMOVE ea, FPCR
770 case 0x5: // FMOVE FPCR, ea
771 {
772 fmove_fpcr(w2);
773 break;
774 }
775
776 case 0x6: // FMOVEM ea, list
777 case 0x7: // FMOVEM list, ea
778 {
779 fmovem(w2);
780 break;
781 }
782
783 default: fatalerror("m68040_fpu_op0: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4);
784 }
785 break;
786 }
787
788 case 2: // FBcc disp16
789 {
790 fbcc16();
791 break;
792 }
793 case 3: // FBcc disp32
794 {
795 fbcc32();
796 break;
797 }
798
799 default: fatalerror("m68040_fpu_op0: unimplemented main op %d\n", (REG_IR >> 6) & 0x3);
800 }
801 }
802
m68040_fpu_op1(void)803 void m68040_fpu_op1(void)
804 {
805 int ea = REG_IR & 0x3f;
806
807 switch ((REG_IR >> 6) & 0x3)
808 {
809 case 0: // FSAVE <ea>
810 {
811 WRITE_EA_32(ea, 0x00000000);
812 // TODO: correct state frame
813 break;
814 }
815
816 case 1: // FRESTORE <ea>
817 {
818 READ_EA_32(ea);
819 // TODO: correct state frame
820 break;
821 }
822
823 default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2);
824 }
825 }
826
827
828
829