static void fmove_fpcr(m68ki_cpu_core *m68k, UINT16 w2) { int ea = m68k->ir & 0x3f; int dir = (w2 >> 13) & 0x1; int reg = (w2 >> 10) & 0x7; if (dir) // From system control reg to <ea> { switch (reg) { case 1: WRITE_EA_32(m68k, ea, REG_FPIAR); break; case 2: WRITE_EA_32(m68k, ea, REG_FPSR); break; case 4: WRITE_EA_32(m68k, ea, REG_FPCR); break; default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir); } } else // From <ea> to system control reg { switch (reg) { case 1: REG_FPIAR = READ_EA_32(m68k, ea); break; case 2: REG_FPSR = READ_EA_32(m68k, ea); break; case 4: REG_FPCR = READ_EA_32(m68k, ea); break; default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir); } } m68k->remaining_cycles -= 10; }
static void fmove_fpcr(UINT16 w2) { int ea = REG_IR & 0x3f; int dir = (w2 >> 13) & 0x1; int reg = (w2 >> 10) & 0x7; if (dir) // From system control reg to <ea> { switch (reg) { case 1: WRITE_EA_32(ea, REG_FPIAR); break; case 2: WRITE_EA_32(ea, REG_FPSR); break; case 4: WRITE_EA_32(ea, REG_FPCR); break; default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir); } } else // From <ea> to system control reg { switch (reg) { case 1: REG_FPIAR = READ_EA_32(ea); break; case 2: REG_FPSR = READ_EA_32(ea); break; case 4: REG_FPCR = READ_EA_32(ea); break; default: fatalerror("fmove_fpcr: unknown reg %d, dir %d\n", reg, dir); } } USE_CYCLES(10); }
static void fmove_reg_mem(m68ki_cpu_core *m68k, UINT16 w2) { int ea = m68k->ir & 0x3f; int src = (w2 >> 7) & 0x7; int dst = (w2 >> 10) & 0x7; //int kfactor = w2 & 0x7f; switch (dst) { case 0: // Long-Word Integer { INT32 d = (INT32)(REG_FP[src].f); WRITE_EA_32(m68k, ea, d); break; } case 1: // Single-precision Real { float f = (float)(REG_FP[src].f); UINT32 d = *(UINT32 *)&f; WRITE_EA_32(m68k, ea, d); break; } case 2: // Extended-precision Real { fatalerror("fmove_reg_mem: extended-precision real store unimplemented at %08X\n", REG_PC-4); break; } case 3: // Packed-decimal Real with Static K-factor { fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4); break; } case 4: // Word Integer { INT16 d = (INT16)(REG_FP[src].f); WRITE_EA_16(m68k, ea, d); break; } case 5: // Double-precision Real { UINT64 d = REG_FP[src].i; WRITE_EA_64(m68k, ea, d); break; } case 6: // Byte Integer { INT8 d = (INT16)(REG_FP[src].f); WRITE_EA_8(m68k, ea, d); break; } case 7: // Packed-decimal Real with Dynamic K-factor { fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4); break; } } m68k->remaining_cycles -= 12; }
static void fmove_reg_mem(UINT16 w2) { int ea = REG_IR & 0x3f; int src = (w2 >> 7) & 0x7; int dst = (w2 >> 10) & 0x7; //int kfactor = w2 & 0x7f; switch (dst) { case 0: // Long-Word Integer { INT32 d = (INT32)(REG_FP[src].f); WRITE_EA_32(ea, d); break; } case 1: // Single-precision Real { float f = (float)(REG_FP[src].f); UINT32 d = *(UINT32 *)&f; WRITE_EA_32(ea, d); break; } case 2: // Extended-precision Real { fatalerror("fmove_reg_mem: extended-precision real store unimplemented at %08X\n", REG_PC-4); break; } case 3: // Packed-decimal Real with Static K-factor { fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4); break; } case 4: // Word Integer { fatalerror("fmove_reg_mem: word integer store unimplemented at %08X\n", REG_PC-4); break; } case 5: // Double-precision Real { UINT64 d = REG_FP[src].i; WRITE_EA_64(ea, d); break; } case 6: // Byte Integer { fatalerror("fmove_reg_mem: byte integer store unimplemented at %08X\n", REG_PC-4); break; } case 7: // Packed-decimal Real with Dynamic K-factor { fatalerror("fmove_reg_mem: packed-decimal real store unimplemented at %08X\n", REG_PC-4); break; } } USE_CYCLES(12); }
static void fmove_fpcr(m68ki_cpu_core *m68k, UINT16 w2) { int ea = m68k->ir & 0x3f; int dir = (w2 >> 13) & 0x1; int regsel = (w2 >> 10) & 0x7; int mode = (ea >> 3) & 0x7; if ((mode == 5) || (mode == 6)) { UINT32 address = 0xffffffff; // force a bus error if this doesn't get assigned if (mode == 5) { address = EA_AY_DI_32(m68k); } else if (mode == 6) { address = EA_AY_IX_32(m68k); } if (dir) // From system control reg to <ea> { if (regsel & 4) { m68ki_write_32(m68k, address, REG_FPCR(m68k)); address += 4; } if (regsel & 2) { m68ki_write_32(m68k, address, REG_FPSR(m68k)); address += 4; } if (regsel & 1) { m68ki_write_32(m68k, address, REG_FPIAR(m68k)); address += 4; } } else // From <ea> to system control reg { if (regsel & 4) { REG_FPCR(m68k) = m68ki_read_32(m68k, address); address += 4; } if (regsel & 2) { REG_FPSR(m68k) = m68ki_read_32(m68k, address); address += 4; } if (regsel & 1) { REG_FPIAR(m68k) = m68ki_read_32(m68k, address); address += 4; } } } else { if (dir) // From system control reg to <ea> { if (regsel & 4) WRITE_EA_32(m68k, ea, REG_FPCR(m68k)); if (regsel & 2) WRITE_EA_32(m68k, ea, REG_FPSR(m68k)); if (regsel & 1) WRITE_EA_32(m68k, ea, REG_FPIAR(m68k)); } else // From <ea> to system control reg { if (regsel & 4) REG_FPCR(m68k) = READ_EA_32(m68k, ea); if (regsel & 2) REG_FPSR(m68k) = READ_EA_32(m68k, ea); if (regsel & 1) REG_FPIAR(m68k) = READ_EA_32(m68k, ea); } } m68k->remaining_cycles -= 10; }
void m68040_fpu_op1(m68ki_cpu_core *m68k) { int ea = m68k->ir & 0x3f; switch ((m68k->ir >> 6) & 0x3) { case 0: // FSAVE <ea> { WRITE_EA_32(m68k, ea, 0x00000000); // TODO: correct state frame break; } case 1: // FRESTORE <ea> { READ_EA_32(m68k, ea); // TODO: correct state frame break; } default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (m68k->ir >> 6) & 0x3, REG_PC-2); } }
void m68040_fpu_op1(void) { int ea = REG_IR & 0x3f; switch ((REG_IR >> 6) & 0x3) { case 0: // FSAVE <ea> { WRITE_EA_32(ea, 0x00000000); // TODO: correct state frame break; } case 1: // FRESTORE <ea> { READ_EA_32(ea); // TODO: correct state frame break; } default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2); } }
static void fmove_fpcr(m68000_base_device *m68k, UINT16 w2) { int ea = m68k->ir & 0x3f; int dir = (w2 >> 13) & 0x1; int regsel = (w2 >> 10) & 0x7; int mode = (ea >> 3) & 0x7; if ((mode == 5) || (mode == 6)) { UINT32 address = 0xffffffff; // force a bus error if this doesn't get assigned if (mode == 5) { address = EA_AY_DI_32(m68k); } else if (mode == 6) { address = EA_AY_IX_32(m68k); } if (dir) // From system control reg to <ea> { if (regsel & 4) { m68ki_write_32(m68k, address, REG_FPCR(m68k)); address += 4; } if (regsel & 2) { m68ki_write_32(m68k, address, REG_FPSR(m68k)); address += 4; } if (regsel & 1) { m68ki_write_32(m68k, address, REG_FPIAR(m68k)); address += 4; } } else // From <ea> to system control reg { if (regsel & 4) { REG_FPCR(m68k) = m68ki_read_32(m68k, address); address += 4; } if (regsel & 2) { REG_FPSR(m68k) = m68ki_read_32(m68k, address); address += 4; } if (regsel & 1) { REG_FPIAR(m68k) = m68ki_read_32(m68k, address); address += 4; } } } else { if (dir) // From system control reg to <ea> { if (regsel & 4) WRITE_EA_32(m68k, ea, REG_FPCR(m68k)); if (regsel & 2) WRITE_EA_32(m68k, ea, REG_FPSR(m68k)); if (regsel & 1) WRITE_EA_32(m68k, ea, REG_FPIAR(m68k)); } else // From <ea> to system control reg { if (regsel & 4) REG_FPCR(m68k) = READ_EA_32(m68k, ea); if (regsel & 2) REG_FPSR(m68k) = READ_EA_32(m68k, ea); if (regsel & 1) REG_FPIAR(m68k) = READ_EA_32(m68k, ea); } } #if 0 // FIXME: (2011-12-18 ost) // rounding_mode and rounding_precision of softfloat.c should be set according to current fpcr // but: with this code on Apollo the following programs in /systest/fptest will fail: // 1. Single Precision Whetstone will return wrong results never the less // 2. Vector Test will fault with 00040004: reference to illegal address if ((regsel & 4) && dir == 0) { int rnd = (REG_FPCR(m68k) >> 4) & 3; int prec = (REG_FPCR(m68k) >> 6) & 3; logerror("m68k_fpsp:fmove_fpcr fpcr=%04x prec=%d rnd=%d\n", REG_FPCR(m68k), prec, rnd); #ifdef FLOATX80 switch (prec) { case 0: // Extend (X) floatx80_rounding_precision = 80; break; case 1: // Single (S) floatx80_rounding_precision = 32; break; case 2: // Double (D) floatx80_rounding_precision = 64; break; case 3: // Undefined floatx80_rounding_precision = 80; break; } #endif switch (rnd) { case 0: // To Nearest (RN) float_rounding_mode = float_round_nearest_even; break; case 1: // To Zero (RZ) float_rounding_mode = float_round_to_zero; break; case 2: // To Minus Infinitiy (RM) float_rounding_mode = float_round_down; break; case 3: // To Plus Infinitiy (RP) float_rounding_mode = float_round_up; break; } }
static void fmove_reg_mem(m68000_base_device *m68k, UINT16 w2) { int ea = m68k->ir & 0x3f; int src = (w2 >> 7) & 0x7; int dst = (w2 >> 10) & 0x7; int k = (w2 & 0x7f); switch (dst) { case 0: // Long-Word Integer { INT32 d = (INT32)floatx80_to_int32(REG_FP(m68k)[src]); WRITE_EA_32(m68k, ea, d); break; } case 1: // Single-precision Real { UINT32 d = floatx80_to_float32(REG_FP(m68k)[src]); WRITE_EA_32(m68k, ea, d); break; } case 2: // Extended-precision Real { WRITE_EA_FPE(m68k, ea, REG_FP(m68k)[src]); break; } case 3: // Packed-decimal Real with Static K-factor { // sign-extend k k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f); WRITE_EA_PACK(m68k, ea, k, REG_FP(m68k)[src]); break; } case 4: // Word Integer { int32 value = floatx80_to_int32(REG_FP(m68k)[src]); if (value > 0x7fff || value < -0x8000 ) { REG_FPSR(m68k) |= FPES_OE | FPAE_IOP; } WRITE_EA_16(m68k, ea, (INT16)value); break; } case 5: // Double-precision Real { UINT64 d; d = floatx80_to_float64(REG_FP(m68k)[src]); WRITE_EA_64(m68k, ea, d); break; } case 6: // Byte Integer { int32 value = floatx80_to_int32(REG_FP(m68k)[src]); if (value > 127 || value < -128) { REG_FPSR(m68k) |= FPES_OE | FPAE_IOP; } WRITE_EA_8(m68k, ea, (INT8) value); break; } case 7: // Packed-decimal Real with Dynamic K-factor { WRITE_EA_PACK(m68k, ea, REG_D(m68k)[k>>4], REG_FP(m68k)[src]); break; } } m68k->remaining_cycles -= 12; }