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; }
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; } }