mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
MIPS3: Add divide by zero floating point exception (nw)
This commit is contained in:
parent
caa8d04ced
commit
43c7b9d8bb
@ -37,6 +37,7 @@
|
||||
#define FTVALS_FR0 (((float *)&m_core->cpr[1][FTREG & 0x1E])[BYTE_XOR_LE(FTREG & 1)])
|
||||
#define FSVALS_FR0 (((float *)&m_core->cpr[1][FSREG & 0x1E])[BYTE_XOR_LE(FSREG & 1)])
|
||||
#define FDVALS_FR0 (((float *)&m_core->cpr[1][FDREG & 0x1E])[BYTE_XOR_LE(FDREG & 1)])
|
||||
#define FTVALW_FR0 (((uint32_t *)&m_core->cpr[1][FTREG & 0x1E])[BYTE_XOR_LE(FTREG & 1)])
|
||||
#define FSVALW_FR0 (((uint32_t *)&m_core->cpr[1][FSREG & 0x1E])[BYTE_XOR_LE(FSREG & 1)])
|
||||
#define FDVALW_FR0 (((uint32_t *)&m_core->cpr[1][FDREG & 0x1E])[BYTE_XOR_LE(FDREG & 1)])
|
||||
|
||||
@ -44,6 +45,7 @@
|
||||
#define FTVALD_FR0 (*(double *)&m_core->cpr[1][FTREG & 0x1E])
|
||||
#define FSVALD_FR0 (*(double *)&m_core->cpr[1][FSREG & 0x1E])
|
||||
#define FDVALD_FR0 (*(double *)&m_core->cpr[1][FDREG & 0x1E])
|
||||
#define FTVALL_FR0 (*(uint64_t *)&m_core->cpr[1][FTREG & 0x1E])
|
||||
#define FSVALL_FR0 (*(uint64_t *)&m_core->cpr[1][FSREG & 0x1E])
|
||||
#define FDVALL_FR0 (*(uint64_t *)&m_core->cpr[1][FDREG & 0x1E])
|
||||
|
||||
@ -1977,10 +1979,28 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
if (IS_SINGLE(op)) /* DIV.S */
|
||||
FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0;
|
||||
else /* DIV.D */
|
||||
FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0;
|
||||
if (IS_SINGLE(op)) { /* DIV.S */
|
||||
if (FTVALW_FR0 == 0 && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) {
|
||||
COP1_FCR31 |= (1 << (FCR31_FLAGS + FPE_DIV0)); // Set flag
|
||||
COP1_FCR31 |= (1 << (FCR31_CAUSE + FPE_DIV0)); // Set cause
|
||||
generate_exception(EXCEPTION_FPE, 1);
|
||||
//machine().debug_break();
|
||||
}
|
||||
else {
|
||||
FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0;
|
||||
}
|
||||
}
|
||||
else { /* DIV.D */
|
||||
if (FTVALL_FR0 == 0ull && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) {
|
||||
COP1_FCR31 |= (1 << (FCR31_FLAGS + FPE_DIV0)); // Set flag
|
||||
COP1_FCR31 |= (1 << (FCR31_CAUSE + FPE_DIV0)); // Set cause
|
||||
generate_exception(EXCEPTION_FPE, 1);
|
||||
//machine().debug_break();
|
||||
}
|
||||
else {
|
||||
FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
|
@ -238,6 +238,9 @@ enum {
|
||||
#define MIPS3_MAX_FASTRAM 3
|
||||
#define MIPS3_MAX_HOTSPOTS 16
|
||||
|
||||
/* COP1 CCR register */
|
||||
#define COP1_FCR31 (m_core->ccr[1][31])
|
||||
|
||||
/***************************************************************************
|
||||
INTERRUPT CONSTANTS
|
||||
***************************************************************************/
|
||||
|
@ -155,10 +155,15 @@
|
||||
#define EXCEPTION_BADCOP 11
|
||||
#define EXCEPTION_OVERFLOW 12
|
||||
#define EXCEPTION_TRAP 13
|
||||
#define EXCEPTION_FPE 15
|
||||
#define EXCEPTION_TLBLOAD_FILL 16
|
||||
#define EXCEPTION_TLBSTORE_FILL 17
|
||||
#define EXCEPTION_COUNT 18
|
||||
|
||||
#define FCR31_FLAGS 2 // FLAGS start bit
|
||||
#define FCR31_ENABLE 7 // Enable start bit
|
||||
#define FCR31_CAUSE 12 // Cause start bit
|
||||
#define FPE_DIV0 3 // Divide by zero bit index
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
@ -247,6 +247,7 @@ void mips3_device::code_flush_cache()
|
||||
static_generate_exception(EXCEPTION_BADCOP, true, "exception_badcop");
|
||||
static_generate_exception(EXCEPTION_OVERFLOW, true, "exception_overflow");
|
||||
static_generate_exception(EXCEPTION_TRAP, true, "exception_trap");
|
||||
static_generate_exception(EXCEPTION_FPE, true, "exception_fpe");
|
||||
|
||||
/* add subroutines for memory accesses */
|
||||
for (mode = 0; mode < 3; mode++)
|
||||
@ -728,6 +729,14 @@ void mips3_device::static_generate_exception(uint8_t exception, int recover, con
|
||||
UML_ROLINS(block, CPR032(COP0_Context), I0, 32-9, 0x7ffff0); // rolins [Context],i0,32-9,0x7ffff0
|
||||
}
|
||||
|
||||
if (exception == EXCEPTION_FPE)
|
||||
{
|
||||
/* set the flag and cause */
|
||||
UML_GETEXP(block, I0); // getexp i0
|
||||
UML_ROLINS(block, CCR132(31), I0, FCR31_FLAGS, 0x0000007c); // rolins [CCR31],i0,FCR31_FLAGS,0x0000007c
|
||||
UML_ROLINS(block, CCR132(31), I0, FCR31_CAUSE, 0x0003f000); // rolins [CCR31],i0,FCR31_CAUSE,0x0003f000
|
||||
}
|
||||
|
||||
/* set the EPC and Cause registers */
|
||||
if (recover)
|
||||
{
|
||||
@ -2778,11 +2787,21 @@ bool mips3_device::generate_cop1(drcuml_block &block, compiler_state &compiler,
|
||||
case 0x03:
|
||||
if (IS_SINGLE(op)) /* DIV.S - MIPS I */
|
||||
{
|
||||
UML_FSDIV(block, FPR32(FDREG), FPR32(FSREG), FPR32(FTREG)); // fsdiv <fdreg>,<fsreg>,<ftreg>
|
||||
UML_TEST(block, FPR32(FTREG), 0xffffffff); // test <ftreg>,-1
|
||||
UML_JMPc(block, COND_NZ, skip = compiler.labelnum++); // jmp skip,NZ
|
||||
UML_TEST(block, CCR132(31), 1 << (FCR31_ENABLE + FPE_DIV0)); // test [FCR31], 1 << DIV0_EN
|
||||
UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_FPE], 1 << FPE_DIV0); // exh FPE,cop,FPE_DIV0
|
||||
UML_LABEL(block, skip); // skip:
|
||||
UML_FSDIV(block, FPR32(FDREG), FPR32(FSREG), FPR32(FTREG)); // fsdiv <fdreg>,<fsreg>,<ftreg>
|
||||
}
|
||||
else /* DIV.D - MIPS I */
|
||||
{
|
||||
UML_FDDIV(block, FPR64(FDREG), FPR64(FSREG), FPR64(FTREG)); // fddiv <fdreg>,<fsreg>,<ftreg>
|
||||
UML_DTEST(block, FPR64(FTREG), 0xffffffff'ffffffffull); // dtest <ftreg>,-1
|
||||
UML_JMPc(block, COND_NZ, skip = compiler.labelnum++); // jmp skip,NZ
|
||||
UML_TEST(block, CCR132(31), 1 << (FCR31_ENABLE + FPE_DIV0)); // test [FCR31], 1 << DIV0_EN
|
||||
UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_FPE], 1 << FPE_DIV0); // exh FPE,cop,FPE_DIV0
|
||||
UML_LABEL(block, skip); // skip:
|
||||
UML_FDDIV(block, FPR64(FDREG), FPR64(FSREG), FPR64(FTREG)); // fddiv <fdreg>,<fsreg>,<ftreg>
|
||||
}
|
||||
return true;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user