mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
- mips3: Add integer divide-by-zero handling to MIPS III cores. [MooglyGuy]
This commit is contained in:
parent
4fc1911e96
commit
3cf16b2eb1
@ -2447,6 +2447,31 @@ inline void mips3_device::set_cop2_creg(int idx, UINT64 val)
|
||||
m_core->ccr[2][idx] = val;
|
||||
}
|
||||
|
||||
inline void mips3_device::handle_integer_divide_by_zero(UINT32 op)
|
||||
{
|
||||
HIVAL64 = (INT32)RSVAL32;
|
||||
if (m_flavor == MIPS3_TYPE_VR4300)
|
||||
{
|
||||
if (RSVAL32 >= 0)
|
||||
{
|
||||
LOVAL64 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOVAL64 = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RSVAL32 >= 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void mips3_device::handle_cop2(UINT32 op)
|
||||
{
|
||||
if (!(SR & SR_COP2))
|
||||
@ -2616,6 +2641,10 @@ void mips3_device::execute_run()
|
||||
LOVAL64 = (INT32)((INT32)RSVAL32 / (INT32)RTVAL32);
|
||||
HIVAL64 = (INT32)((INT32)RSVAL32 % (INT32)RTVAL32);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_integer_divide_by_zero(op);
|
||||
}
|
||||
m_core->icount -= 35;
|
||||
break;
|
||||
case 0x1b: /* DIVU */
|
||||
@ -2624,6 +2653,10 @@ void mips3_device::execute_run()
|
||||
LOVAL64 = (INT32)(RSVAL32 / RTVAL32);
|
||||
HIVAL64 = (INT32)(RSVAL32 % RTVAL32);
|
||||
}
|
||||
else
|
||||
{
|
||||
handle_integer_divide_by_zero(op);
|
||||
}
|
||||
m_core->icount -= 35;
|
||||
break;
|
||||
case 0x1c: /* DMULT */
|
||||
|
@ -511,6 +511,7 @@ private:
|
||||
UINT64 get_cop2_creg(int idx);
|
||||
void set_cop2_creg(int idx, UINT64 val);
|
||||
void handle_cop2(UINT32 op);
|
||||
void handle_integer_divide_by_zero(UINT32 op);
|
||||
void lwl_be(UINT32 op);
|
||||
void lwr_be(UINT32 op);
|
||||
void ldl_be(UINT32 op);
|
||||
@ -756,6 +757,7 @@ private:
|
||||
#define MIPS3DRC_STRICT_COP2 0x0008 /* validate all COP2 instructions */
|
||||
#define MIPS3DRC_FLUSH_PC 0x0010 /* flush the PC value before each memory access */
|
||||
#define MIPS3DRC_CHECK_OVERFLOWS 0x0020 /* actually check overflows on add/sub instructions */
|
||||
#define MIPS3DRC_ACCURATE_DIVZERO 0x0040 /* load correct values into HI/LO on integer divide-by-zero */
|
||||
|
||||
#define MIPS3DRC_COMPATIBLE_OPTIONS (MIPS3DRC_STRICT_VERIFY | MIPS3DRC_STRICT_COP1 | MIPS3DRC_STRICT_COP0 | MIPS3DRC_STRICT_COP2 | MIPS3DRC_FLUSH_PC)
|
||||
#define MIPS3DRC_FASTEST_OPTIONS (0)
|
||||
|
@ -2054,15 +2054,79 @@ int mips3_device::generate_special(drcuml_block *block, compiler_state *compiler
|
||||
return TRUE;
|
||||
|
||||
case 0x1a: /* DIV - MIPS I */
|
||||
UML_DIVS(block, I0, I1, R32(RSREG), R32(RTREG)); // divs i0,i1,<rsreg>,<rtreg>
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
|
||||
{
|
||||
if (m_drcoptions & MIPS3DRC_ACCURATE_DIVZERO)
|
||||
{
|
||||
code_label divzero, done;
|
||||
|
||||
UML_CMP(block, R32(RTREG), 0); // cmp <rtreg>, 0
|
||||
UML_JMPc(block, COND_E, divzero = compiler->labelnum++); // jmp divzero,E
|
||||
|
||||
UML_DIVS(block, I0, I1, R32(RSREG), R32(RTREG)); // divs i0,i1,<rsreg>,<rtreg>
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
|
||||
UML_JMP(block, done = compiler->labelnum++); // jmp done
|
||||
|
||||
UML_LABEL(block, divzero); // divzero:
|
||||
if (m_flavor != MIPS3_TYPE_VR4300)
|
||||
{
|
||||
UML_MOVc(block, COND_L, I0, 0x00000001); // mov i0,0x00000001,L
|
||||
UML_MOVc(block, COND_GE, I0, 0xffffffff); // mov i0,0xffffffff,GE
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_MOVc(block, COND_L, I0, 0x80000001); // mov i0,0x80000001,L
|
||||
UML_MOVc(block, COND_GE, I0, 0x7fffffff); // mov i0,0x7fffffff,GE
|
||||
}
|
||||
UML_DSEXT(block, HI64, R32(RSREG), SIZE_DWORD); // dsext hi,<rsreg>,dword
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
|
||||
UML_LABEL(block, done); // done:
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_DIVS(block, I0, I1, R32(RSREG), R32(RTREG)); // divs i0,i1,<rsreg>,<rtreg>
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case 0x1b: /* DIVU - MIPS I */
|
||||
UML_DIVU(block, I0, I1, R32(RSREG), R32(RTREG)); // divu i0,i1,<rsreg>,<rtreg>
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
|
||||
if (m_drcoptions & MIPS3DRC_ACCURATE_DIVZERO)
|
||||
{
|
||||
code_label divzero, done;
|
||||
|
||||
UML_CMP(block, R32(RTREG), 0); // cmp <rtreg>, 0
|
||||
UML_JMPc(block, COND_E, divzero = compiler->labelnum++); // jmp divzero,E
|
||||
|
||||
UML_DIVU(block, I0, I1, R32(RSREG), R32(RTREG)); // divu i0,i1,<rsreg>,<rtreg>
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
|
||||
UML_JMP(block, done = compiler->labelnum++); // jmp done
|
||||
|
||||
UML_LABEL(block, divzero); // divzero:
|
||||
if (m_flavor != MIPS3_TYPE_VR4300)
|
||||
{
|
||||
UML_MOVc(block, COND_L, I0, 0x00000001); // mov i0,0x00000001,L
|
||||
UML_MOVc(block, COND_GE, I0, 0xffffffff); // mov i0,0xffffffff,GE
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_MOVc(block, COND_L, I0, 0x80000001); // mov i0,0x80000001,L
|
||||
UML_MOVc(block, COND_GE, I0, 0x7fffffff); // mov i0,0x7fffffff,GE
|
||||
}
|
||||
UML_DSEXT(block, HI64, R32(RSREG), SIZE_DWORD); // dsext hi,<rsreg>,dword
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
|
||||
UML_LABEL(block, done); // done:
|
||||
}
|
||||
else
|
||||
{
|
||||
UML_DIVU(block, I0, I1, R32(RSREG), R32(RTREG)); // divu i0,i1,<rsreg>,<rtreg>
|
||||
UML_DSEXT(block, LO64, I0, SIZE_DWORD); // dsext lo,i0,dword
|
||||
UML_DSEXT(block, HI64, I1, SIZE_DWORD); // dsext hi,i1,dword
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case 0x1e: /* DDIV - MIPS III */
|
||||
|
Loading…
Reference in New Issue
Block a user