diff options
Diffstat (limited to 'src/devices/cpu/tlcs90/tlcs90.cpp')
-rw-r--r-- | src/devices/cpu/tlcs90/tlcs90.cpp | 179 |
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); |