summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tlcs90/tlcs90.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tlcs90/tlcs90.cpp')
-rw-r--r--src/devices/cpu/tlcs90/tlcs90.cpp179
1 files changed, 143 insertions, 36 deletions
diff --git a/src/devices/cpu/tlcs90/tlcs90.cpp b/src/devices/cpu/tlcs90/tlcs90.cpp
index 19684a0d080..be2f05a181a 100644
--- a/src/devices/cpu/tlcs90/tlcs90.cpp
+++ b/src/devices/cpu/tlcs90/tlcs90.cpp
@@ -13,10 +13,12 @@
*************************************************************************************************************/
#include "emu.h"
-#include "debugger.h"
#include "tlcs90.h"
#include "tlcs90d.h"
+#define VERBOSE 0
+#include "logmacro.h"
+
ALLOW_SAVE_TYPE(tlcs90_device::e_mode); // allow save_item on a non-fundamental type
@@ -32,11 +34,11 @@ void tlcs90_device::tmp90840_regs(address_map &map)
{
map(0xffc0, 0xffef).rw(FUNC(tlcs90_device::reserved_r), FUNC(tlcs90_device::reserved_w));
//map(0xffc0, 0xffc0).rw(FUNC(tlcs90_device::p0_r), FUNC(tlcs90_device::p0_w));
- //map(0xffc1, 0xffc1).rw(FUNC(tlcs90_device::p1_r), FUNC(tlcs90_device::p1_w));
- //map(0xffc2, 0xffc2).rw(FUNC(tlcs90_device::irfl_r), FUNC(tlcs90_device::p01cr_w));
+ map(0xffc1, 0xffc1).rw(FUNC(tlcs90_device::p1_r), FUNC(tlcs90_device::p1_w));
+ map(0xffc2, 0xffc2). /*r(FUNC(tlcs90_device::irfl_r)).*/ w(FUNC(tlcs90_device::p01cr_w));
map(0xffc3, 0xffc3). /*r(FUNC(tlcs90_device::irfh_r)).*/ w(FUNC(tlcs90_device::irf_clear_w));
- //map(0xffc4, 0xffc4).rw(FUNC(tlcs90_device::p2_r), FUNC(tlcs90_device::p2_w));
- //map(0xffc5, 0xffc5).w(FUNC(tlcs90_device::p2cr_w));
+ map(0xffc4, 0xffc4).rw(FUNC(tlcs90_device::p2_r), FUNC(tlcs90_device::p2_w));
+ map(0xffc5, 0xffc5).w(FUNC(tlcs90_device::p2cr_w));
map(0xffc6, 0xffc6).rw(FUNC(tlcs90_device::p3_r), FUNC(tlcs90_device::p3_w));
//map(0xffc7, 0xffc7).w(FUNC(tlcs90_device::p3cr_w));
map(0xffc8, 0xffc8).rw(FUNC(tlcs90_device::p4_r), FUNC(tlcs90_device::p4_w));
@@ -107,8 +109,8 @@ void tlcs90_device::tmp90844_regs(address_map &map)
//map(0xffc1, 0xffc1).w(FUNC(tlcs90_device::p0cr_w));
//map(0xffc2, 0xffc2).rw(FUNC(tlcs90_device::p1_r), FUNC(tlcs90_device::p1_w));
//map(0xffc3, 0xffc3).w(FUNC(tlcs90_device::p1cr_w));
- //map(0xffc4, 0xffc4).rw(FUNC(tlcs90_device::p2_r), FUNC(tlcs90_device::p2_w));
- //map(0xffc5, 0xffc5).w(FUNC(tlcs90_device::p2cr_w));
+ map(0xffc4, 0xffc4).rw(FUNC(tlcs90_device::p2_r), FUNC(tlcs90_device::p2_w));
+ map(0xffc5, 0xffc5).w(FUNC(tlcs90_device::p2cr_w));
map(0xffc6, 0xffc6).rw(FUNC(tlcs90_device::p3_r), FUNC(tlcs90_device::p3_w));
//map(0xffc7, 0xffc7).w(FUNC(tlcs90_device::p3cr_w));
map(0xffc8, 0xffc8).rw(FUNC(tlcs90_device::p4_r), FUNC(tlcs90_device::p4_w));
@@ -158,7 +160,7 @@ void tlcs90_device::tmp90ph44_mem(address_map &map)
tlcs90_device::tlcs90_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map)
: cpu_device(mconfig, type, tag, owner, clock)
, m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0, program_map)
- , m_port_read_cb(*this)
+ , m_port_read_cb(*this, 0xff)
, m_port_write_cb(*this)
{
}
@@ -209,7 +211,7 @@ device_memory_interface::space_config_vector tlcs90_device::memory_space_config(
enum {
T90_B, T90_C, T90_D, T90_E, T90_H, T90_L, T90_A,
T90_BC, T90_DE, T90_HL, T90_XX, T90_IX, T90_IY, T90_SP,
- T90_AF, T90_PC
+ T90_AF, T90_PC, T90_HA
};
// Regs
@@ -1022,6 +1024,7 @@ void tlcs90_device::decode()
if (b0 == 0xfe) {
OPCC( LDI+b1-0x58,14,18 ) NONE( 1 ) NONE( 2 ) return;
}
+ break;
case 0x60: // ADD A,g
case 0x61: // ADC A,g
@@ -1077,6 +1080,7 @@ void tlcs90_device::decode()
if (b0 == 0xfe) {
OPCC( RET,6,14 ) CC( 1, b1 - 0xd0 ) NONE( 2 ) return; // RET cc
}
+ break;
} break;
case 0xff:
@@ -1099,7 +1103,7 @@ uint16_t tlcs90_device::r8( const uint16_t r )
case L: return m_hl.b.l;
default:
- fatalerror("%04x: unimplemented r8 register index = %d\n",m_pc.w.l,r);
+ fatalerror("%04x: unimplemented r8 register index = %d\n",m_prvpc.w.l,r);
}
}
@@ -1116,7 +1120,7 @@ void tlcs90_device::w8( const uint16_t r, uint16_t value )
case L: m_hl.b.l = value; return;
default:
- fatalerror("%04x: unimplemented w8 register index = %d\n",m_pc.w.l,r);
+ fatalerror("%04x: unimplemented w8 register index = %d\n",m_prvpc.w.l,r);
}
}
@@ -1137,7 +1141,7 @@ uint16_t tlcs90_device::r16( const uint16_t r )
case PC: return m_pc.w.l;
default:
- fatalerror("%04x: unimplemented r16 register index = %d\n",m_pc.w.l,r);
+ fatalerror("%04x: unimplemented r16 register index = %d\n",m_prvpc.w.l,r);
}
}
@@ -1156,7 +1160,7 @@ void tlcs90_device::w16( const uint16_t r, uint16_t value )
case PC: m_pc.d = value; return;
default:
- fatalerror("%04x: unimplemented w16 register index = %d\n",m_pc.w.l,r);
+ fatalerror("%04x: unimplemented w16 register index = %d\n",m_prvpc.w.l,r);
}
}
@@ -1289,7 +1293,7 @@ int tlcs90_device::Test( uint8_t cond )
case NZ: return !(F & ZF);
case NC: return !(F & CF);
default:
- fatalerror("%04x: unimplemented condition = %d\n",m_pc.w.l,cond);
+ fatalerror("%04x: unimplemented condition = %d\n",m_prvpc.w.l,cond);
}
// never executed
@@ -1342,12 +1346,19 @@ INT2 P82 Rising Edge -
*************************************************************************************************************/
+void tlcs90_device::halt()
+{
+ LOG("%04X: halt\n", m_prvpc.w.l);
+ m_halt = 1;
+}
+
void tlcs90_device::leave_halt()
{
if( m_halt )
{
+ LOG("%04X: leave_halt\n", m_pc.w.l);
m_halt = 0;
- m_pc.w.l++;
+ //m_pc.w.l++;
}
}
@@ -1390,8 +1401,10 @@ void tlcs90_device::check_interrupts()
{
mask = (1 << irq);
if(irq >= INT0) mask &= m_irq_mask;
+
if (m_irq_state & mask)
{
+ LOG("%04X: check_interrupts: taking interrupt: %d. Current state: %x. Current mask: %x\n", m_pc.w.l, irq, m_irq_state, mask);
take_interrupt( irq );
return;
}
@@ -1448,14 +1461,20 @@ void tlcs90_device::execute_run()
do
{
- m_prvpc.d = m_pc.d;
- debugger_instruction_hook(m_pc.d);
-
check_interrupts();
- m_addr = m_pc.d;
- decode();
- m_pc.d = m_addr;
+ // when in HALT state, the fetched opcode is not dispatched (aka a NOP) and the PC is not increased
+ if (m_halt)
+ m_op = NOP;
+ else
+ {
+ m_prvpc.d = m_pc.d;
+ debugger_instruction_hook(m_pc.d);
+
+ m_addr = m_pc.d;
+ decode();
+ m_pc.d = m_addr;
+ }
switch ( m_op )
{
@@ -1629,9 +1648,10 @@ void tlcs90_device::execute_run()
Cyc();
break;
-// case HALT:
-// Cyc();
-// break;
+ case HALT:
+ halt();
+ Cyc();
+ break;
case DI:
m_after_EI = 0;
F &= ~IF;
@@ -2077,6 +2097,8 @@ void tlcs90_device::execute_run()
void tlcs90_device::device_reset()
{
+ leave_halt();
+
m_irq_state = 0;
m_irq_mask = 0;
m_pc.d = 0x0000;
@@ -2090,6 +2112,8 @@ void tlcs90_device::device_reset()
*/
std::fill(std::begin(m_port_latch), std::end(m_port_latch), 0);
+ m_p01cr = 0;
+ m_p2cr = 0;
m_p4cr = 0;
m_p67cr = 0;
m_p8cr = 0;
@@ -2383,6 +2407,89 @@ FFED BX R/W Reset Description
*************************************************************************************************************/
+uint8_t tlcs90_device::p1_r()
+{
+ if ((m_p01cr & 0x04) != 0)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%04X: Read from P1 but it's configured as part of address bus\n", m_prvpc.w.l);
+
+ return 0;
+ }
+
+ if ((m_p01cr & 0x02) != 0)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%04X: Read from P1 but it's configured as output\n", m_prvpc.w.l);
+
+ return 0;
+ }
+
+ return m_port_read_cb[1]();
+}
+
+void tlcs90_device::p1_w(uint8_t data)
+{
+ if ((m_p01cr & 0x04) != 0)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%04X: Read from P1 but it's configured as part of address bus\n", m_prvpc.w.l);
+
+ return;
+ }
+
+ if ((m_p01cr & 0x02) == 0)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%04X: Write to P1 but it's configured as input\n", m_prvpc.w.l);
+
+ return;
+ }
+
+ m_port_write_cb[1](m_port_latch[1]);
+}
+
+void tlcs90_device::p01cr_w(uint8_t data)
+{
+ m_p01cr = data;
+}
+
+uint8_t tlcs90_device::p2_r()
+{
+ if ((m_p01cr & 0x04) != 0)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%04X: Read from P2 but it's configured as part of address bus\n", m_prvpc.w.l);
+
+ return 0;
+ }
+
+ return m_port_read_cb[2]();
+}
+
+void tlcs90_device::p2_w(uint8_t data)
+{
+ if ((m_p01cr & 0x04) != 0)
+ {
+ if (!machine().side_effects_disabled())
+ logerror("%04X: Read from P1 but it's configured as part of address bus\n", m_prvpc.w.l);
+
+ return;
+ }
+
+ m_port_latch[2] = data;
+ uint8_t out_mask = m_p2cr;
+ if (out_mask)
+ {
+ m_port_write_cb[2](m_port_latch[2] & out_mask);
+ }
+}
+
+void tlcs90_device::p2cr_w(uint8_t data)
+{
+ m_p2cr = data;
+}
+
uint8_t tlcs90_device::p3_r()
{
// 7,4,1,0
@@ -2671,14 +2778,14 @@ uint8_t tlcs90_device::reserved_r(offs_t offset)
{
uint16_t iobase = 0xffc0;
if (!machine().side_effects_disabled())
- logerror("%04X: Read from unimplemented SFR at %04X\n", m_pc.w.l, iobase + offset);
+ logerror("%04X: Read from unimplemented SFR at %04X\n", m_prvpc.w.l, iobase + offset);
return 0;
}
void tlcs90_device::reserved_w(offs_t offset, uint8_t data)
{
uint16_t iobase = 0xffc0;
- logerror("%04X: Write %02X to unimplemented SFR at %04X\n", m_pc.w.l, data, iobase + offset);
+ logerror("%04X: Write %02X to unimplemented SFR at %04X\n", m_prvpc.w.l, data, iobase + offset);
}
void tlcs90_device::t90_start_timer(int i)
@@ -2720,7 +2827,7 @@ void tlcs90_device::t90_start_timer(int i)
m_timer[i]->adjust(period, i, period);
- logerror("%04X: CPU Timer %d started at %f Hz\n", m_pc.w.l, i, 1.0 / period.as_double());
+ LOG("%04X: CPU Timer %d started at %f Hz\n", m_pc.w.l, i, 1.0 / period.as_double());
}
void tlcs90_device::t90_start_timer4()
@@ -2742,14 +2849,14 @@ void tlcs90_device::t90_start_timer4()
m_timer[4]->adjust(period, 4, period);
- logerror("%04X: CPU Timer 4 started at %f Hz\n", m_pc.w.l, 1.0 / period.as_double());
+ LOG("%04X: CPU Timer 4 started at %f Hz\n", m_pc.w.l, 1.0 / period.as_double());
}
void tlcs90_device::t90_stop_timer(int i)
{
m_timer[i]->adjust(attotime::never, i);
- logerror("%04X: CPU Timer %d stopped\n", m_pc.w.l, i);
+ LOG("%04X: CPU Timer %d stopped\n", m_pc.w.l, i);
}
void tlcs90_device::t90_stop_timer4()
@@ -2776,6 +2883,7 @@ TIMER_CALLBACK_MEMBER( tlcs90_device::t90_timer_callback )
case 0x03: // 8bit PWM
logerror("CPU Timer %d expired with unhandled mode %d\n", i, mode);
// TODO: hmm...
+ [[fallthrough]]; // FIXME: really?
case 0x00: // 8bit
m_timer_value[i]++;
if ( m_timer_value[i] == m_treg_8bit[i] )
@@ -2803,7 +2911,7 @@ TIMER_CALLBACK_MEMBER( tlcs90_device::t90_timer_callback )
if(i & 1)
break;
if ( (m_tclk & (0x0C << (i * 2))) == 0 ) // T0/T1 match signal clocks T1/T3
- t90_timer_callback(ptr, i+1);
+ t90_timer_callback(i+1);
break;
case 0x01: // 16bit, only can happen for i=0,2
m_timer_value[i+1] = 0;
@@ -2848,9 +2956,6 @@ TIMER_CALLBACK_MEMBER( tlcs90_device::t90_timer4_callback )
void tlcs90_device::device_start()
{
- m_port_read_cb.resolve_all_safe(0xff);
- m_port_write_cb.resolve_all_safe();
-
save_item(NAME(m_prvpc.w.l));
save_item(NAME(m_pc.w.l));
save_item(NAME(m_sp.w.l));
@@ -2872,6 +2977,8 @@ void tlcs90_device::device_start()
save_item(NAME(m_extra_cycles));
save_item(NAME(m_port_latch));
+ save_item(NAME(m_p01cr));
+ save_item(NAME(m_p2cr));
save_item(NAME(m_p4cr));
save_item(NAME(m_p67cr));
save_item(NAME(m_p8cr));
@@ -2948,9 +3055,9 @@ void tlcs90_device::device_start()
// Timers
for (int i = 0; i < 4; i++)
- m_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tlcs90_device::t90_timer_callback),this));
+ m_timer[i] = timer_alloc(FUNC(tlcs90_device::t90_timer_callback), this);
- m_timer[4] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tlcs90_device::t90_timer4_callback),this));
+ m_timer[4] = timer_alloc(FUNC(tlcs90_device::t90_timer4_callback), this);
state_add( T90_PC, "PC", m_pc.w.l).formatstr("%04X");
state_add( T90_SP, "SP", m_sp.w.l).formatstr("%04X");
@@ -2967,10 +3074,10 @@ void tlcs90_device::device_start()
state_add( T90_HL, "HL", m_hl.w.l).formatstr("%04X");
state_add( T90_IX, "IX", m_ix.w.l).formatstr("%04X");
state_add( T90_IY, "IY", m_iy.w.l).formatstr("%04X");
+ state_add( T90_HA, "HALT", m_halt).formatstr("%01X");
state_add(STATE_GENPC, "GENPC", m_pc.w.l).formatstr("%04X").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_prvpc.w.l).formatstr("%04X").noshow();
- state_add(STATE_GENSP, "GENSP", m_sp.w.l).formatstr("%04X").noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", F ).formatstr("%8s").noshow();
set_icountptr(m_icount);