static void WRITE_EA_64(m68ki_cpu_core *m68k, int ea, UINT64 data) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea = REG_A[reg]; m68ki_write_32(m68k, ea, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea, (UINT32)(data)); break; } case 4: // -(An) { UINT32 ea; REG_A[reg] -= 8; ea = REG_A[reg]; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } 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); } }
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; }
INLINE void store_extended_float80(m68000_base_device *m68k, UINT32 ea, floatx80 fpr) { m68ki_write_16(m68k, ea+0, fpr.high); m68ki_write_16(m68k, ea+2, 0); m68ki_write_32(m68k, ea+4, (fpr.low>>32)&0xffffffff); m68ki_write_32(m68k, ea+8, fpr.low&0xffffffff); }
static void WRITE_EA_FPE(m68ki_cpu_core *m68k, int ea, fp_reg fpr) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); // TODO: convert to extended floating-point! switch (mode) { case 4: // -(An) { UINT32 ea; REG_A[reg] -= 12; ea = REG_A[reg]; m68ki_write_32(m68k, ea+0, (UINT32)(fpr.i >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(fpr.i)); m68ki_write_32(m68k, ea+8, 0); break; } default: fatalerror("MC68040: WRITE_EA_FPE: unhandled mode %d, reg %d, data %f at %08X\n", mode, reg, fpr.f, REG_PC); } }
static void WRITE_EA_32(m68ki_cpu_core *m68k, int ea, UINT32 data) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 0: // Dn { REG_D[reg] = data; break; } case 2: // (An) { UINT32 ea = REG_A[reg]; m68ki_write_32(m68k, ea, data); break; } case 3: // (An)+ { UINT32 ea = EA_AY_PI_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 4: // -(An) { UINT32 ea = EA_AY_PD_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 6: // (An) + (Xn) + d8 { UINT32 ea = EA_AY_IX_32(m68k); m68ki_write_32(m68k, ea, data); break; } case 7: { switch (reg) { case 1: // (xxx).L { UINT32 d1 = OPER_I_16(m68k); UINT32 d2 = OPER_I_16(m68k); UINT32 ea = (d1 << 16) | d2; m68ki_write_32(m68k, ea, data); break; } case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); m68ki_write_32(m68k, ea, data); break; } default: fatalerror("MC68040: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); } break; } default: fatalerror("MC68040: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); } }
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; } }
INLINE void store_pack_float80(m68000_base_device *m68k, UINT32 ea, int k, floatx80 fpr) { UINT32 dw1, dw2, dw3; char str[128], *ch; int i, j, exp; dw1 = dw2 = dw3 = 0; ch = &str[0]; sprintf(str, "%.16e", fx80_to_double(fpr)); if (*ch == '-') { ch++; dw1 = 0x80000000; } if (*ch == '+') { ch++; } dw1 |= (*ch++ - '0'); if (*ch == '.') { ch++; } // handle negative k-factor here if ((k <= 0) && (k >= -13)) { exp = 0; for (i = 0; i < 3; i++) { if (ch[18+i] >= '0' && ch[18+i] <= '9') { exp = (exp << 4) | (ch[18+i] - '0'); } } if (ch[17] == '-') { exp = -exp; } k = -k; // last digit is (k + exponent - 1) k += (exp - 1); // round up the last significant mantissa digit if (ch[k+1] >= '5') { ch[k]++; } // zero out the rest of the mantissa digits for (j = (k+1); j < 16; j++) { ch[j] = '0'; } // now zero out K to avoid tripping the positive K detection below k = 0; } // crack 8 digits of the mantissa for (i = 0; i < 8; i++) { dw2 <<= 4; if (*ch >= '0' && *ch <= '9') { dw2 |= *ch++ - '0'; } } // next 8 digits of the mantissa for (i = 0; i < 8; i++) { dw3 <<= 4; if (*ch >= '0' && *ch <= '9') dw3 |= *ch++ - '0'; } // handle masking if k is positive if (k >= 1) { if (k <= 17) { dw2 &= pkmask2[k]; dw3 &= pkmask3[k]; } else { dw2 &= pkmask2[17]; dw3 &= pkmask3[17]; // m68k->fpcr |= (need to set OPERR bit) } } // finally, crack the exponent if (*ch == 'e' || *ch == 'E') { ch++; if (*ch == '-') { ch++; dw1 |= 0x40000000; } if (*ch == '+') { ch++; } j = 0; for (i = 0; i < 3; i++) { if (*ch >= '0' && *ch <= '9') { j = (j << 4) | (*ch++ - '0'); } } dw1 |= (j << 16); } m68ki_write_32(m68k, ea, dw1); m68ki_write_32(m68k, ea+4, dw2); m68ki_write_32(m68k, ea+8, dw3); }
static void WRITE_EA_64(m68000_base_device *m68k, int ea, UINT64 data) { int mode = (ea >> 3) & 0x7; int reg = (ea & 0x7); switch (mode) { case 2: // (An) { UINT32 ea = REG_A(m68k)[reg]; m68ki_write_32(m68k, ea, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 3: // (An)+ { UINT32 ea = REG_A(m68k)[reg]; REG_A(m68k)[reg] += 8; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 4: // -(An) { UINT32 ea; REG_A(m68k)[reg] -= 8; ea = REG_A(m68k)[reg]; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 5: // (d16, An) { UINT32 ea = EA_AY_DI_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 6: // (An) + (Xn) + d8 { UINT32 ea = EA_AY_IX_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 7: { switch (reg) { case 1: // (xxx).L { UINT32 d1 = OPER_I_16(m68k); UINT32 d2 = OPER_I_16(m68k); UINT32 ea = (d1 << 16) | d2; m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } case 2: // (d16, PC) { UINT32 ea = EA_PCDI_32(m68k); m68ki_write_32(m68k, ea+0, (UINT32)(data >> 32)); m68ki_write_32(m68k, ea+4, (UINT32)(data)); break; } default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC(m68k)); } break; } 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(m68k)); } }