tms32051: more bug fixes (nw)

This commit is contained in:
Ville Linde 2015-12-31 20:03:11 +02:00
parent 5a5fcfb17d
commit 4131fb6dfd
4 changed files with 112 additions and 88 deletions

View File

@ -15,19 +15,19 @@ UINT16 tms32051_device::POP_STACK()
return pc; return pc;
} }
INT32 tms32051_device::SUB(UINT32 a, UINT32 b, int shift) INT32 tms32051_device::SUB(UINT32 a, UINT32 b, bool shift16)
{ {
UINT32 res = a - b; UINT32 res = a - b;
if (shift > 0) if (shift16)
{ {
// C is cleared if borrow was generated, otherwise unaffected // C is cleared if borrow was generated, otherwise unaffected
if (b > a) m_st1.c = 0; if (a < res) m_st1.c = 0;
} }
else else
{ {
// C is cleared if borrow was generated // C is cleared if borrow was generated
m_st1.c = (b > a) ? 0 : 1; m_st1.c = (a < res) ? 0 : 1;
} }
// check overflow // check overflow
@ -45,11 +45,11 @@ INT32 tms32051_device::SUB(UINT32 a, UINT32 b, int shift)
return (INT32)(res); return (INT32)(res);
} }
INT32 tms32051_device::ADD(UINT32 a, UINT32 b, int shift) INT32 tms32051_device::ADD(UINT32 a, UINT32 b, bool shift16)
{ {
UINT32 res = a + b; UINT32 res = a + b;
if (shift > 0) if (shift16)
{ {
// C is set if carry was generated, otherwise unaffected // C is set if carry was generated, otherwise unaffected
if (a > res) m_st1.c = 1; if (a > res) m_st1.c = 1;
@ -196,67 +196,58 @@ UINT16 tms32051_device::GET_ADDRESS()
} }
} }
int tms32051_device::GET_ZLVC_CONDITION(int zlvc, int zlvc_mask) bool tms32051_device::GET_ZLVC_CONDITION(int zlvc, int zlvc_mask)
{ {
if (zlvc_mask & 0x2) // OV-bit if (zlvc_mask & 0x2) // OV-bit
{ {
if ((zlvc & 0x2) && m_st0.ov) // OV if ((zlvc & 0x2) && m_st0.ov == 0) // OV
{ return false;
// clear OV if (((zlvc & 0x2) == 0) && m_st0.ov != 0) // NOV
m_st0.ov = 0; return false;
}
if (zlvc_mask & 0x1) // C-bit
{
if ((zlvc & 0x1) && m_st1.c == 0) // C
return false;
if (((zlvc & 0x1) == 0) && m_st1.c != 0) // NC
return false;
}
if (zlvc_mask & 0x8) // Z-bit
{
if ((zlvc & 0x8) && (INT32)(m_acc) != 0) // EQ
return false;
if (((zlvc & 0x8) == 0) && (INT32)(m_acc) == 0) // NEQ
return false;
}
if (zlvc_mask & 0x4) // L-bit
{
if ((zlvc & 0x4) && (INT32)(m_acc) >= 0) // LT
return false;
if (((zlvc & 0x4) == 0) && (INT32)(m_acc) <= 0) // GT
return false;
}
return 1; return true;
}
else if ((zlvc & 0x2) == 0 && m_st0.ov == 0) // NOV
return 1;
}
if (zlvc_mask & 0x1) // C-bit
{
if ((zlvc & 0x1) && m_st1.c) // C
return 1;
else if ((zlvc & 0x1) == 0 && m_st1.c == 0) // NC
return 1;
}
if (zlvc_mask & 0x8) // Z-bit
{
if ((zlvc & 0x8) && (INT32)(m_acc) == 0) // EQ
return 1;
else if ((zlvc & 0x8) == 0 && (INT32)(m_acc) != 0) // NEQ
return 1;
}
if (zlvc_mask & 0x4) // L-bit
{
if ((zlvc & 0x4) && (INT32)(m_acc) < 0) // LT
return 1;
else if ((zlvc & 0x4) == 0 && (INT32)(m_acc) > 0) // GT
return 1;
}
return 0;
} }
int tms32051_device::GET_TP_CONDITION(int tp) bool tms32051_device::GET_TP_CONDITION(int tp)
{ {
switch (tp) switch (tp)
{ {
case 0: // BIO pin low case 0: // BIO pin low
{
// TODO // TODO
return 0; return false;
}
case 1: // TC = 1 case 1: // TC == 1
{ return m_st1.tc != 0;
return m_st1.tc;
} case 2: // TC == 0
case 2: // TC = 0 return m_st1.tc == 0;
{
return m_st1.tc ^ 1; case 3:
} return true;
case 3: // always false
{
return 0;
}
} }
return 0; return true;
} }
INT32 tms32051_device::PREG_PSCALER(INT32 preg) INT32 tms32051_device::PREG_PSCALER(INT32 preg)
@ -318,7 +309,7 @@ void tms32051_device::op_add_mem()
d = (UINT32)(UINT16)(data) << shift; d = (UINT32)(UINT16)(data) << shift;
} }
m_acc = ADD(m_acc, d, shift); m_acc = ADD(m_acc, d, false);
CYCLES(1); CYCLES(1);
} }
@ -327,7 +318,7 @@ void tms32051_device::op_add_simm()
{ {
UINT16 imm = m_op & 0xff; UINT16 imm = m_op & 0xff;
m_acc = ADD(m_acc, imm, 0); m_acc = ADD(m_acc, imm, false);
CYCLES(1); CYCLES(1);
} }
@ -347,7 +338,7 @@ void tms32051_device::op_add_limm()
d = (UINT32)(UINT16)(imm) << shift; d = (UINT32)(UINT16)(imm) << shift;
} }
m_acc = ADD(m_acc, d, shift); m_acc = ADD(m_acc, d, false);
CYCLES(2); CYCLES(2);
} }
@ -357,14 +348,14 @@ void tms32051_device::op_add_s16_mem()
UINT16 ea = GET_ADDRESS(); UINT16 ea = GET_ADDRESS();
UINT32 data = DM_READ16(ea) << 16; UINT32 data = DM_READ16(ea) << 16;
m_acc = ADD(m_acc, data, 0); m_acc = ADD(m_acc, data, true);
CYCLES(1); CYCLES(1);
} }
void tms32051_device::op_addb() void tms32051_device::op_addb()
{ {
m_acc = ADD(m_acc, m_accb, 0); m_acc = ADD(m_acc, m_accb, false);
CYCLES(1); CYCLES(1);
} }
@ -694,7 +685,12 @@ void tms32051_device::op_satl()
void tms32051_device::op_sbb() void tms32051_device::op_sbb()
{ {
m_acc = SUB(m_acc, m_accb, 0); UINT32 res = m_acc - m_accb;
// C is cleared if borrow was generated
m_st1.c = ((UINT32)(m_acc) < res) ? 0 : 1;
m_acc = res;
CYCLES(1); CYCLES(1);
} }
@ -761,7 +757,7 @@ void tms32051_device::op_sub_mem()
d = (UINT32)(UINT16)(data) << shift; d = (UINT32)(UINT16)(data) << shift;
} }
m_acc = SUB(m_acc, d, shift); m_acc = SUB(m_acc, d, false);
CYCLES(1); CYCLES(1);
} }
@ -775,7 +771,7 @@ void tms32051_device::op_sub_simm()
{ {
UINT16 imm = m_op & 0xff; UINT16 imm = m_op & 0xff;
m_acc = SUB(m_acc, imm, 0); m_acc = SUB(m_acc, imm, false);
CYCLES(1); CYCLES(1);
} }
@ -795,7 +791,7 @@ void tms32051_device::op_sub_limm()
d = (UINT32)(UINT16)(imm) << shift; d = (UINT32)(UINT16)(imm) << shift;
} }
m_acc = SUB(m_acc, d, shift); m_acc = SUB(m_acc, d, false);
CYCLES(2); CYCLES(2);
} }
@ -1037,10 +1033,14 @@ void tms32051_device::op_bcnd()
{ {
UINT16 pma = ROPCODE(); UINT16 pma = ROPCODE();
if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
CHANGE_PC(pma); CHANGE_PC(pma);
CYCLES(4); CYCLES(4);
// clear overflow
if (m_op & 0x2)
m_st0.ov = 0;
} }
else else
{ {
@ -1052,8 +1052,12 @@ void tms32051_device::op_bcndd()
{ {
UINT16 pma = ROPCODE(); UINT16 pma = ROPCODE();
if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
// clear overflow
if (m_op & 0x2)
m_st0.ov = 0;
delay_slot(m_pc); delay_slot(m_pc);
CHANGE_PC(pma); CHANGE_PC(pma);
CYCLES(4); CYCLES(4);
@ -1121,12 +1125,16 @@ void tms32051_device::op_cc()
{ {
UINT16 pma = ROPCODE(); UINT16 pma = ROPCODE();
if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
PUSH_STACK(m_pc); PUSH_STACK(m_pc);
CHANGE_PC(pma); CHANGE_PC(pma);
CYCLES(4); CYCLES(4);
// clear overflow
if (m_op & 0x2)
m_st0.ov = 0;
} }
else else
{ {
@ -1138,10 +1146,14 @@ void tms32051_device::op_ccd()
{ {
UINT16 pma = ROPCODE(); UINT16 pma = ROPCODE();
if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
PUSH_STACK(m_pc+2); PUSH_STACK(m_pc+2);
// clear overflow
if (m_op & 0x2)
m_st0.ov = 0;
delay_slot(m_pc); delay_slot(m_pc);
CHANGE_PC(pma); CHANGE_PC(pma);
} }
@ -1161,7 +1173,7 @@ void tms32051_device::op_nmi()
void tms32051_device::op_retc() void tms32051_device::op_retc()
{ {
if ((m_op & 0x3ff) == 0x300 || GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
UINT16 pc = POP_STACK(); UINT16 pc = POP_STACK();
CHANGE_PC(pc); CHANGE_PC(pc);
@ -1175,7 +1187,7 @@ void tms32051_device::op_retc()
void tms32051_device::op_retcd() void tms32051_device::op_retcd()
{ {
if ((m_op & 0x3ff) == 0x300 || GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
UINT16 pc = POP_STACK(); UINT16 pc = POP_STACK();
delay_slot(m_pc); delay_slot(m_pc);
@ -1212,7 +1224,7 @@ void tms32051_device::op_trap()
void tms32051_device::op_xc() void tms32051_device::op_xc()
{ {
if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) || GET_TP_CONDITION((m_op >> 8) & 0x3)) if (GET_ZLVC_CONDITION((m_op >> 4) & 0xf, m_op & 0xf) && GET_TP_CONDITION((m_op >> 8) & 0x3))
{ {
CYCLES(1); CYCLES(1);
} }
@ -1359,7 +1371,7 @@ void tms32051_device::op_out()
{ {
UINT16 port = ROPCODE(); UINT16 port = ROPCODE();
UINT16 ea = GET_ADDRESS(); UINT16 ea = GET_ADDRESS();
UINT16 data = DM_READ16(ea); UINT16 data = DM_READ16(ea);
m_io->write_word(port << 1, data); m_io->write_word(port << 1, data);
@ -1421,7 +1433,11 @@ void tms32051_device::op_apl_dbmr()
{ {
UINT16 ea = GET_ADDRESS(); UINT16 ea = GET_ADDRESS();
UINT16 data = DM_READ16(ea); UINT16 data = DM_READ16(ea);
data &= m_dbmr; data &= m_dbmr;
m_st1.tc = (data == 0) ? 1 : 0;
DM_WRITE16(ea, data); DM_WRITE16(ea, data);
CYCLES(1); CYCLES(1);
} }
@ -1431,7 +1447,11 @@ void tms32051_device::op_apl_imm()
UINT16 ea = GET_ADDRESS(); UINT16 ea = GET_ADDRESS();
UINT16 imm = ROPCODE(); UINT16 imm = ROPCODE();
UINT16 data = DM_READ16(ea); UINT16 data = DM_READ16(ea);
data &= imm; data &= imm;
m_st1.tc = (data == 0) ? 1 : 0;
DM_WRITE16(ea, data); DM_WRITE16(ea, data);
CYCLES(1); CYCLES(1);
} }
@ -1457,6 +1477,9 @@ void tms32051_device::op_opl_dbmr()
UINT16 ea = GET_ADDRESS(); UINT16 ea = GET_ADDRESS();
UINT16 data = DM_READ16(ea); UINT16 data = DM_READ16(ea);
data |= m_dbmr; data |= m_dbmr;
m_st1.tc = (data == 0) ? 1 : 0;
DM_WRITE16(ea, data); DM_WRITE16(ea, data);
CYCLES(1); CYCLES(1);
} }
@ -1467,6 +1490,9 @@ void tms32051_device::op_opl_imm()
UINT16 imm = ROPCODE(); UINT16 imm = ROPCODE();
UINT16 data = DM_READ16(ea); UINT16 data = DM_READ16(ea);
data |= imm; data |= imm;
m_st1.tc = (data == 0) ? 1 : 0;
DM_WRITE16(ea, data); DM_WRITE16(ea, data);
CYCLES(1); CYCLES(1);
} }
@ -1494,7 +1520,7 @@ void tms32051_device::op_xpl_imm()
void tms32051_device::op_apac() void tms32051_device::op_apac()
{ {
INT32 spreg = PREG_PSCALER(m_preg); INT32 spreg = PREG_PSCALER(m_preg);
m_acc = ADD(m_acc, spreg, 0); m_acc = ADD(m_acc, spreg, false);
CYCLES(1); CYCLES(1);
} }
@ -1527,7 +1553,7 @@ void tms32051_device::op_lta()
m_treg0 = data; m_treg0 = data;
spreg = PREG_PSCALER(m_preg); spreg = PREG_PSCALER(m_preg);
m_acc = ADD(m_acc, spreg, 0); m_acc = ADD(m_acc, spreg, false);
if (m_pmst.trm == 0) if (m_pmst.trm == 0)
{ {
m_treg1 = data; m_treg1 = data;

View File

@ -231,8 +231,8 @@ static void dasm_group_be(UINT16 opcode)
case 0x82: print("or #%04X", FETCH() << 16); break; case 0x82: print("or #%04X", FETCH() << 16); break;
case 0x83: print("xor #%04X", FETCH() << 16); break; case 0x83: print("xor #%04X", FETCH() << 16); break;
case 0xc4: print("rpt #%04X", FETCH()); break; case 0xc4: print("rpt #%04X", FETCH()); break;
case 0xc5: print("rpt #%04X", FETCH()); break; case 0xc5: print("rptz #%04X", FETCH()); break;
case 0xc6: print("rpt #%04X", FETCH()); break; case 0xc6: print("rptb #%04X", FETCH()); break;
default: print("??? (group be)"); break; default: print("??? (group be)"); break;
} }

View File

@ -38,10 +38,9 @@ enum
TMS32051_AR7, TMS32051_AR7,
TMS32051_IFR, TMS32051_IFR,
TMS32051_IMR, TMS32051_IMR,
TMS32051_ST0_ARP,
TMS32051_ST0_INTM, TMS32051_ST0_INTM,
TMS32051_ST0_DP,
TMS32051_ST1_ARB, TMS32051_ST1_ARB,
TMS32051_ST1_TC,
TMS32051_TIM, TMS32051_TIM,
TMS32051_PSC TMS32051_PSC
}; };
@ -238,10 +237,9 @@ void tms32051_device::device_start()
state_add( TMS32051_IFR, "IFR", m_ifr).formatstr("%04X"); state_add( TMS32051_IFR, "IFR", m_ifr).formatstr("%04X");
state_add( TMS32051_IMR, "IMR", m_imr).formatstr("%04X"); state_add( TMS32051_IMR, "IMR", m_imr).formatstr("%04X");
state_add( TMS32051_ST0_ARP, "ST0 ARP", m_st0.arp).formatstr("%1d"); state_add( TMS32051_ST0_INTM, "ST0_INTM", m_st0.intm).formatstr("%1d");
state_add( TMS32051_ST0_INTM, "ST0 INTM", m_st0.intm).formatstr("%1d"); state_add( TMS32051_ST1_ARB, "ST1_ARB", m_st1.arb).formatstr("%04X");
state_add( TMS32051_ST0_DP, "ST0 DP", m_st0.dp).formatstr("%04X"); state_add( TMS32051_ST1_TC, "ST1_TC", m_st1.tc).formatstr("%1d");
state_add( TMS32051_ST1_ARB, "ST1 ARB", m_st1.arb).formatstr("%04X");
state_add( TMS32051_TIM, "TIM", m_timer.tim).formatstr("%04X"); state_add( TMS32051_TIM, "TIM", m_timer.tim).formatstr("%04X");
state_add( TMS32051_PSC, "PSC", m_timer.psc).formatstr("%04X"); state_add( TMS32051_PSC, "PSC", m_timer.psc).formatstr("%04X");

View File

@ -175,13 +175,13 @@ protected:
inline void DM_WRITE16(UINT16 address, UINT16 data); inline void DM_WRITE16(UINT16 address, UINT16 data);
inline void PUSH_STACK(UINT16 pc); inline void PUSH_STACK(UINT16 pc);
inline UINT16 POP_STACK(); inline UINT16 POP_STACK();
inline INT32 SUB(UINT32 a, UINT32 b, int shift); inline INT32 SUB(UINT32 a, UINT32 b, bool shift16);
inline INT32 ADD(UINT32 a, UINT32 b, int shift); inline INT32 ADD(UINT32 a, UINT32 b, bool shift16);
inline void UPDATE_AR(int ar, int step); inline void UPDATE_AR(int ar, int step);
inline void UPDATE_ARP(int nar); inline void UPDATE_ARP(int nar);
UINT16 GET_ADDRESS(); UINT16 GET_ADDRESS();
inline int GET_ZLVC_CONDITION(int zlvc, int zlvc_mask); inline bool GET_ZLVC_CONDITION(int zlvc, int zlvc_mask);
inline int GET_TP_CONDITION(int tp); inline bool GET_TP_CONDITION(int tp);
inline INT32 PREG_PSCALER(INT32 preg); inline INT32 PREG_PSCALER(INT32 preg);
void op_invalid(); void op_invalid();
void op_abs(); void op_abs();