diff options
Diffstat (limited to 'src/devices/cpu/tlcs90/tlcs90.cpp')
-rw-r--r-- | src/devices/cpu/tlcs90/tlcs90.cpp | 886 |
1 files changed, 564 insertions, 322 deletions
diff --git a/src/devices/cpu/tlcs90/tlcs90.cpp b/src/devices/cpu/tlcs90/tlcs90.cpp index 6333be73025..40ba8291c7c 100644 --- a/src/devices/cpu/tlcs90/tlcs90.cpp +++ b/src/devices/cpu/tlcs90/tlcs90.cpp @@ -6,17 +6,15 @@ emulation by Luca Elia, based on the Z80 core by Juergen Buchmueller - ChangeLog: - - 20150517 Fixed TRUN bit masking (timers start/stop handling) [Rainer Keuchel] - *************************************************************************************************************/ #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 @@ -28,60 +26,138 @@ DEFINE_DEVICE_TYPE(TMP91641, tmp91641_device, "tmp91641", "Toshiba TMP91641") DEFINE_DEVICE_TYPE(TMP90PH44, tmp90ph44_device, "tmp90ph44", "Toshiba TMP90PH44") -#define T90_IOBASE 0xffc0 - -enum e_ir +void tlcs90_device::tmp90840_regs(address_map &map) { - T90_P0=T90_IOBASE, T90_P1, T90_P01CR_IRFL, T90_IRFH, T90_P2, T90_P2CR, T90_P3, T90_P3CR, - T90_P4, T90_P4CR, T90_P5, T90_SMMOD, T90_P6, T90_P7, T90_P67CR, T90_SMCR, - T90_P8, T90_P8CR, T90_WDMOD, T90_WDCR, T90_TREG0, T90_TREG1, T90_TREG2, T90_TREG3, - T90_TCLK, T90_TFFCR, T90_TMOD, T90_TRUN, T90_CAP1L, T90_CAP1H, T90_CAP2L, T90_CAL2H, - T90_TREG4L, T90_TREG4H, T90_TREG5L, T90_TREG5H, T90_T4MOD, T90_T4FFCR, T90_INTEL, T90_INTEH, - T90_DMAEH, T90_SCMOD, T90_SCCR, T90_SCBUF, T90_BX, T90_BY, T90_ADREG, T90_ADMOD -}; - + 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). /*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(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)); + map(0xffc9, 0xffc9).w(FUNC(tlcs90_device::p4cr_w)); + map(0xffca, 0xffca).r(FUNC(tlcs90_device::p5_r)); + map(0xffcb, 0xffcb).rw(FUNC(tlcs90_device::smmod_r), FUNC(tlcs90_device::smmod_w)); + map(0xffcc, 0xffcc).rw(FUNC(tlcs90_device::p6_r), FUNC(tlcs90_device::p6_w)); + map(0xffcd, 0xffcd).rw(FUNC(tlcs90_device::p7_r), FUNC(tlcs90_device::p7_w)); + map(0xffce, 0xffce).w(FUNC(tlcs90_device::p67cr_w)); + //map(0xffcf, 0xffcf).rw(FUNC(tlcs90_device::smcr_r), FUNC(tlcs90_device::smcr_w)); + map(0xffd0, 0xffd0).rw(FUNC(tlcs90_device::p8_r), FUNC(tlcs90_device::p8_w)); + map(0xffd1, 0xffd1).w(FUNC(tlcs90_device::p8cr_w)); + //map(0xffd2, 0xffd2).rw(FUNC(tlcs90_device::wdmod_r), FUNC(tlcs90_device::wdmod_w)); + //map(0xffd3, 0xffd3).w(FUNC(tlcs90_device::wdcr_w)); + map(0xffd4, 0xffd7).w(FUNC(tlcs90_device::treg_8bit_w)); + map(0xffd8, 0xffd8).rw(FUNC(tlcs90_device::tclk_r), FUNC(tlcs90_device::tclk_w)); + //map(0xffd9, 0xffd9).rw(FUNC(tlcs90_device::tffcr_r), FUNC(tlcs90_device::tffcr_w)); + map(0xffda, 0xffda).rw(FUNC(tlcs90_device::tmod_r), FUNC(tlcs90_device::tmod_w)); + map(0xffdb, 0xffdb).rw(FUNC(tlcs90_device::trun_r), FUNC(tlcs90_device::trun_w)); + //map(0xffdc, 0xffdf).r(FUNC(tlcs90_device::cap_16bit_r)); + map(0xffe0, 0xffe3).w(FUNC(tlcs90_device::treg_16bit_w)); + map(0xffe4, 0xffe4).rw(FUNC(tlcs90_device::t4mod_r), FUNC(tlcs90_device::t4mod_w)); + //map(0xffe5, 0xffe5).rw(FUNC(tlcs90_device::t4ffcr_r), FUNC(tlcs90_device::t4ffcr_w)); + map(0xffe6, 0xffe6). /*r(FUNC(tlcs90_device::intel_r).*/ w(FUNC(tlcs90_device::intel_w)); + map(0xffe7, 0xffe7). /*r(FUNC(tlcs90_device::inteh_r).*/ w(FUNC(tlcs90_device::inteh_w)); + //map(0xffe8, 0xffe8).rw(FUNC(tlcs90_device::dmaeh_r), FUNC(tlcs90_device::dmaeh_w)); + //map(0xffe9, 0xffe9).rw(FUNC(tlcs90_device::scmod_r), FUNC(tlcs90_device::scmod_w)); + //map(0xffea, 0xffea).rw(FUNC(tlcs90_device::sccr_r), FUNC(tlcs90_device::sccr_w)); + //map(0xffeb, 0xffeb).rw(FUNC(tlcs90_device::scbuf_r), FUNC(tlcs90_device::scbuf_w)); + map(0xffec, 0xffec).rw(FUNC(tlcs90_device::bx_r), FUNC(tlcs90_device::bx_w)); + map(0xffed, 0xffed).rw(FUNC(tlcs90_device::by_r), FUNC(tlcs90_device::by_w)); + //map(0xffee, 0xffee).r(FUNC(tlcs90_device::adreg_r)); + //map(0xffef, 0xffef).rw(FUNC(tlcs90_device::admod_r), FUNC(tlcs90_device::admod_w)); +} void tlcs90_device::tmp90840_mem(address_map &map) { map(0x0000, 0x1fff).rom(); // 8KB ROM (internal) map(0xfec0, 0xffbf).ram(); // 256b RAM (internal) - map(T90_IOBASE, T90_IOBASE+47).rw(FUNC(tlcs90_device::t90_internal_registers_r), FUNC(tlcs90_device::t90_internal_registers_w)); + tmp90840_regs(map); } void tlcs90_device::tmp90841_mem(address_map &map) { -// AM_RANGE( 0x0000, 0x1fff ) AM_ROM // rom-less +// map(0x0000, 0x1fff).rom(); // rom-less map(0xfec0, 0xffbf).ram(); // 256b RAM (internal) - map(T90_IOBASE, T90_IOBASE+47).rw(FUNC(tlcs90_device::t90_internal_registers_r), FUNC(tlcs90_device::t90_internal_registers_w)); + tmp90840_regs(map); } void tlcs90_device::tmp91640_mem(address_map &map) { map(0x0000, 0x3fff).rom(); // 16KB ROM (internal) map(0xfdc0, 0xffbf).ram(); // 512b RAM (internal) - map(T90_IOBASE, T90_IOBASE+47).rw(FUNC(tlcs90_device::t90_internal_registers_r), FUNC(tlcs90_device::t90_internal_registers_w)); + tmp90840_regs(map); } void tlcs90_device::tmp91641_mem(address_map &map) { -// AM_RANGE( 0x0000, 0x3fff ) AM_ROM // rom-less +// map(0x0000, 0x3fff).rom(); // rom-less map(0xfdc0, 0xffbf).ram(); // 512b RAM (internal) - map(T90_IOBASE, T90_IOBASE+47).rw(FUNC(tlcs90_device::t90_internal_registers_r), FUNC(tlcs90_device::t90_internal_registers_w)); + tmp90840_regs(map); +} + +void tlcs90_device::tmp90844_regs(address_map &map) +{ + map(0xffc0, 0xfff7).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).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(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)); + //map(0xffc9, 0xffc9).w(FUNC(tlcs90_device::p4cr_w)); + map(0xffca, 0xffca).r(FUNC(tlcs90_device::p5_r)) /*w(FUNC(tlcs90_device::p5_w))*/; + map(0xffcb, 0xffcb).rw(FUNC(tlcs90_device::p6_r), FUNC(tlcs90_device::p6_w)); + map(0xffcc, 0xffcc).rw(FUNC(tlcs90_device::p7_r), FUNC(tlcs90_device::p7_w)); + map(0xffcd, 0xffcd).w(FUNC(tlcs90_device::p67cr_w)); + //map(0xffce, 0xffce).rw(FUNC(tlcs90_device::p23fr_r), FUNC(tlcs90_device::p23fr_w)); + //map(0xffcf, 0xffcf).rw(FUNC(tlcs90_device::p4fr_r), FUNC(tlcs90_device::p4fr_w)); + //map(0xffd0, 0xffd0).rw(FUNC(tlcs90_device::p67fr_r), FUNC(tlcs90_device::p67fr_w)); + //map(0xffd1, 0xffd1).rw(FUNC(tlcs90_device::p25fr_r), FUNC(tlcs90_device::p25fr_w)); + //map(0xffd2, 0xffd2).rw(FUNC(tlcs90_device::wdmod_r), FUNC(tlcs90_device::wdmod_w)); + //map(0xffd3, 0xffd3).w(FUNC(tlcs90_device::wdcr_w)); + map(0xffd4, 0xffd7).w(FUNC(tlcs90_device::treg_8bit_w)); + map(0xffd8, 0xffd8).rw(FUNC(tlcs90_device::t01mod_r), FUNC(tlcs90_device::t01mod_w)); + map(0xffd9, 0xffd9).rw(FUNC(tlcs90_device::t23mod_r), FUNC(tlcs90_device::t23mod_w)); + //map(0xffda, 0xffda).rw(FUNC(tlcs90_device::tffcr_r), FUNC(tlcs90_device::tffcr_w)); + //map(0xffdb, 0xffdb).rw(FUNC(tlcs90_device::trdc_r), FUNC(tlcs90_device::trdc_w)); + map(0xffdc, 0xffdc).rw(FUNC(tlcs90_device::trun_r), FUNC(tlcs90_device::trun_w)); + map(0xffe0, 0xffe3). /*r(FUNC(tlcs90_device::cap_16bit_r)).*/ w(FUNC(tlcs90_device::treg_16bit_w)); + map(0xffe4, 0xffe4).rw(FUNC(tlcs90_device::t4mod_r), FUNC(tlcs90_device::t4mod_w)); + //map(0xffe5, 0xffe5).rw(FUNC(tlcs90_device::t4ffcr_r), FUNC(tlcs90_device::t4ffcr_w)); + //map(0xffe6, 0xffe6).rw(FUNC(tlcs90_device::scmod_r), FUNC(tlcs90_device::scmod_w)); + //map(0xffe7, 0xffe7).rw(FUNC(tlcs90_device::sccr_r), FUNC(tlcs90_device::sccr_w)); + //map(0xffe8, 0xffe8).rw(FUNC(tlcs90_device::scbuf_r), FUNC(tlcs90_device::scbuf_w)); + //map(0xffe9, 0xffe9).rw(FUNC(tlcs90_device::brgcr_r), FUNC(tlcs90_device::brgcr_w)); + map(0xffea, 0xffea). /*r(FUNC(tlcs90_device::irfl_r).*/ w(FUNC(tlcs90_device::irf_clear_w)); + //map(0xffeb, 0xffeb).rw(FUNC(tlcs90_device::irfh_r), FUNC(tlcs90_device::p1fr_w)); + //map(0xffef, 0xffef).rw(FUNC(tlcs90_device::status_r), FUNC(tlcs90_device::status_w)); + //map(0xffef, 0xffef).rw(FUNC(tlcs90_device::admod_r), FUNC(tlcs90_device::admod_w)); + //map(0xfff0, 0xfff3).r(FUNC(tlcs90_device::adreg_r)); + map(0xfff4, 0xfff4). /*r(FUNC(tlcs90_device::intel_r).*/ w(FUNC(tlcs90_device::intel_w)); + map(0xfff5, 0xfff5). /*r(FUNC(tlcs90_device::inteh_r).*/ w(FUNC(tlcs90_device::inteh_w)); + //map(0xfff6, 0xfff6).rw(FUNC(tlcs90_device::dmael_r), FUNC(tlcs90_device::dmael_w)); + //map(0xfff7, 0xfff7).rw(FUNC(tlcs90_device::dmaeh_r), FUNC(tlcs90_device::dmaeh_w)); } void tlcs90_device::tmp90ph44_mem(address_map &map) { map(0x0000, 0x3fff).rom(); // 16KB PROM (internal) map(0xfdc0, 0xffbf).ram(); // 512b RAM (internal) - map(T90_IOBASE, T90_IOBASE+55).rw(FUNC(tlcs90_device::t90_internal_registers_r), FUNC(tlcs90_device::t90_internal_registers_w)); // TODO: has 8 more registers + tmp90844_regs(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}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} - , m_port_write_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} + , m_port_read_cb(*this, 0xff) + , m_port_write_cb(*this) { } @@ -131,7 +207,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 @@ -204,31 +280,28 @@ static uint8_t SZHV_dec[256]; /* zero, sign, half carry and overflow flags DEC r #define OP_16 0x80 - - - -#define OP( X,CT ) m_op = X; m_cyc_t = (CT*2); -#define OP16( X,CT ) OP( (X)|OP_16,CT ) - -#define OPCC( X,CF,CT ) OP( X, CT ) m_cyc_f = (CF*2); -#define OPCC16( X,CF,CT ) OPCC( (X)|OP_16,CF,CT ) - -#define BIT8( N,I ) m_mode##N = e_mode::BIT8; m_r##N = I; -#define I8( N,I ) m_mode##N = e_mode::I8; m_r##N = I; -#define D8( N,I ) m_mode##N = e_mode::D8; m_r##N = I; -#define I16( N,I ) m_mode##N = e_mode::I16; m_r##N = I; -#define D16( N,I ) m_mode##N = e_mode::D16; m_r##N = I; -#define R8( N,R ) m_mode##N = e_mode::R8; m_r##N = R; -#define R16( N,R ) m_mode##N = e_mode::R16; m_r##N = R; -#define Q16( N,R ) m_mode##N = e_mode::R16; m_r##N = R; if (m_r##N == SP) m_r##N = AF; -#define MI16( N,I ) m_mode##N = e_mode::MI16; m_r##N = I; -#define MR16( N,R ) m_mode##N = e_mode::MR16; m_r##N = R; -#define MR16D8( N,R,I ) m_mode##N = e_mode::MR16D8; m_r##N = R; m_r##N##b = I; -#define MR16R8( N,R,g ) m_mode##N = e_mode::MR16R8; m_r##N = R; m_r##N##b = g; -#define NONE( N ) m_mode##N = e_mode::NONE; -#define CC( N,cc ) m_mode##N = e_mode::CC; m_r##N = cc; -#define R16D8( N,R,I ) m_mode##N = e_mode::R16D8; m_r##N = R; m_r##N##b = I; -#define R16R8( N,R,g ) m_mode##N = e_mode::R16R8; m_r##N = R; m_r##N##b = g; +#define OP( X,CT ) m_op = X; m_cyc_t = (CT*2); +#define OP16( X,CT ) OP( (X)|OP_16,CT ) + +#define OPCC( X,CF,CT ) OP( X, CT ) m_cyc_f = (CF*2); +#define OPCC16( X,CF,CT ) OPCC( (X)|OP_16,CF,CT ) + +#define BIT8( N,I ) m_mode##N = e_mode::BIT8; m_r##N = I; +#define I8( N,I ) m_mode##N = e_mode::I8; m_r##N = I; +#define D8( N,I ) m_mode##N = e_mode::D8; m_r##N = I; +#define I16( N,I ) m_mode##N = e_mode::I16; m_r##N = I; +#define D16( N,I ) m_mode##N = e_mode::D16; m_r##N = I; +#define R8( N,R ) m_mode##N = e_mode::R8; m_r##N = R; +#define R16( N,R ) m_mode##N = e_mode::R16; m_r##N = R; +#define Q16( N,R ) m_mode##N = e_mode::R16; m_r##N = R; if (m_r##N == SP) m_r##N = AF; +#define MI16( N,I ) m_mode##N = e_mode::MI16; m_r##N = I; +#define MR16( N,R ) m_mode##N = e_mode::MR16; m_r##N = R; +#define MR16D8( N,R,I ) m_mode##N = e_mode::MR16D8; m_r##N = R; m_r##N##b = I; +#define MR16R8( N,R,g ) m_mode##N = e_mode::MR16R8; m_r##N = R; m_r##N##b = g; +#define NONE( N ) m_mode##N = e_mode::NONE; +#define CC( N,cc ) m_mode##N = e_mode::CC; m_r##N = cc; +#define R16D8( N,R,I ) m_mode##N = e_mode::R16D8; m_r##N = R; m_r##N##b = I; +#define R16R8( N,R,g ) m_mode##N = e_mode::R16R8; m_r##N = R; m_r##N##b = g; uint8_t tlcs90_device::RM8 (uint32_t a) { return m_program->read_byte( a ); } uint16_t tlcs90_device::RM16(uint32_t a) { return RM8(a) | (RM8( (a+1) & 0xffff ) << 8); } @@ -944,6 +1017,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 @@ -999,6 +1073,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: @@ -1021,7 +1096,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); } } @@ -1038,7 +1113,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); } } @@ -1059,7 +1134,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); } } @@ -1078,7 +1153,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); } } @@ -1211,7 +1286,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 @@ -1264,12 +1339,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++; } } @@ -1312,8 +1394,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; } @@ -1370,14 +1454,23 @@ 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) + { + debugger_wait_hook(); + 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 ) { @@ -1551,9 +1644,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; @@ -1999,6 +2093,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; @@ -2012,6 +2108,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; @@ -2028,11 +2126,6 @@ void tlcs90_device::device_reset() std::fill(std::begin(m_treg_16bit), std::end(m_treg_16bit), 0); } -void tlcs90_device::execute_burn(int32_t cycles) -{ - m_icount -= 4 * ((cycles + 3) / 4); -} - /************************************************************************************************************* @@ -2305,51 +2398,387 @@ FFED BX R/W Reset Description *************************************************************************************************************/ -READ8_MEMBER( tlcs90_device::t90_internal_registers_r ) +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) { - switch ( T90_IOBASE + offset ) + m_p2cr = data; +} + +uint8_t tlcs90_device::p3_r() +{ + // 7,4,1,0 + return (m_port_latch[3] & 0x6c) | (m_port_read_cb[3]() & 0x93); +} + +void tlcs90_device::p3_w(uint8_t data) +{ + m_port_latch[3] = data & 0x6c; + m_port_write_cb[3](m_port_latch[3]); +} + +uint8_t tlcs90_device::p4_r() +{ + // only output + return m_port_latch[4] & 0x0f; +} + +void tlcs90_device::p4_w(uint8_t data) +{ + m_port_latch[4] = data & 0x0f; + uint8_t out_mask = ~m_p4cr & 0x0f; + if (out_mask) + { + m_port_write_cb[4](m_port_latch[4] & out_mask); + } +} + +void tlcs90_device::p4cr_w(uint8_t data) +{ + m_p4cr = data; +} + +uint8_t tlcs90_device::p5_r() +{ + return m_port_read_cb[5]() & 0x3f; +} + +uint8_t tlcs90_device::p6_r() +{ + return (m_port_latch[6] & 0xf0) | (m_port_read_cb[6]() & 0x0f); +} + +void tlcs90_device::p6_w(uint8_t data) +{ + m_port_latch[6] = data & 0x0f; + uint8_t out_mask = m_p67cr & 0x0f; + switch (m_smmod & 0x03) + { + case 1: + data &= ~0x01; + // add TO1 here + break; + case 2: + case 3: + data &= ~0x0f; + // add M0 here + break; + } + + if (out_mask) + { + m_port_write_cb[6](m_port_latch[6] & out_mask); + } +} + +uint8_t tlcs90_device::p7_r() +{ + return (m_port_latch[7] & 0xf0) | (m_port_read_cb[7]() & 0x0f); +} + +void tlcs90_device::p7_w(uint8_t data) +{ + m_port_latch[7] = data & 0x0f; + uint8_t out_mask = m_p67cr >> 4; + switch ((m_smmod >> 4) & 0x03) + { + case 1: + data &= ~0x01; + // add TO3 here + break; + case 2: + case 3: + data &= ~0x0f; + // add M1 here + break; + } + + if (out_mask) + { + m_port_write_cb[7](m_port_latch[7] & out_mask); + } +} + +void tlcs90_device::p67cr_w(uint8_t data) +{ + m_p67cr = data; +} + +uint8_t tlcs90_device::p8_r() +{ + // 2,1,0 + return (m_port_latch[8] & 0x08) | (m_port_read_cb[8]() & 0x07); +} + +void tlcs90_device::p8_w(uint8_t data) +{ + m_port_latch[8] = data & 0x0f; + uint8_t out_mask = ~m_p8cr & 0x08; + if (out_mask) { - case T90_P3: // 7,4,1,0 - return (m_port_latch[3] & 0x6c) | (m_port_read_cb[3]() & 0x93); + m_port_write_cb[8](m_port_latch[8] & out_mask); + } +} + +void tlcs90_device::p8cr_w(uint8_t data) +{ + m_p8cr = data; +} + +uint8_t tlcs90_device::smmod_r() +{ + return 0x88 | m_smmod; +} + +void tlcs90_device::smmod_w(uint8_t data) +{ + m_smmod = data; +} + +uint8_t tlcs90_device::tmod_r() +{ + return m_tmod; +} + +void tlcs90_device::tmod_w(uint8_t data) +{ + m_tmod = data; +} + +uint8_t tlcs90_device::tclk_r() +{ + return m_tclk; +} + +void tlcs90_device::tclk_w(uint8_t data) +{ + m_tclk = data; +} + +uint8_t tlcs90_device::t01mod_r() +{ + return (m_tmod & 0x0f) << 4 | (m_tclk & 0x0f); +} - case T90_P4: // only output - return m_port_latch[4] & 0x0f; +void tlcs90_device::t01mod_w(uint8_t data) +{ + m_tmod = (m_tmod & 0xf0) | (data & 0xf0) >> 4; + m_tclk = (m_tclk & 0xf0) | (data & 0x0f); +} - case T90_P5: - return (m_port_read_cb[5]() & 0x3f); +uint8_t tlcs90_device::t23mod_r() +{ + return (m_tmod & 0xf0) | (m_tclk & 0xf0) >> 4; +} - case T90_P6: - return (m_port_latch[6] & 0xf0) | (m_port_read_cb[6]() & 0x0f); +void tlcs90_device::t23mod_w(uint8_t data) +{ + m_tmod = (data & 0xf0) | (m_tmod & 0x0f); + m_tclk = (data & 0x0f) << 4 | (m_tclk & 0x0f); +} - case T90_P7: - return (m_port_latch[7] & 0xf0) | (m_port_read_cb[7]() & 0x0f); +void tlcs90_device::treg_8bit_w(offs_t offset, uint8_t data) +{ + m_treg_8bit[offset] = data; +} - case T90_P8: // 2,1,0 - return (m_port_latch[8] & 0x08) | (m_port_read_cb[8]() & 0x07); +uint8_t tlcs90_device::t4mod_r() +{ + return m_t4mod; +} - case T90_BX: - return 0xf0 | (m_ixbase >> 16); +void tlcs90_device::t4mod_w(uint8_t data) +{ + m_t4mod = data; +} - case T90_BY: - return 0xf0 | (m_iybase >> 16); +void tlcs90_device::treg_16bit_w(offs_t offset, uint8_t data) +{ + if (util::BIT(offset, 0)) + m_treg_16bit[offset >> 1] = (m_treg_16bit[offset >> 1] & 0x00ff) | (data << 8); + else + m_treg_16bit[offset >> 1] = (m_treg_16bit[offset >> 1] & 0xff00) | data; +} - case T90_TMOD: - return m_tmod; +uint8_t tlcs90_device::trun_r() +{ + return m_trun; +} - case T90_TCLK: - return m_tclk; +void tlcs90_device::trun_w(uint8_t data) +{ + uint8_t old = m_trun; - case T90_TRUN: - return m_trun; + // Timers 0-3 + for (int i = 0; i < 4; i++) + { + uint8_t mask = 0x20 | (1 << i); + if ( (old ^ data) & mask ) // if timer bit or prescaler bit changed + { + if ( (data & mask) == mask ) t90_start_timer(i); + else t90_stop_timer(i); + } + } - case T90_T4MOD: - return m_t4mod; + // Timer 4 + uint8_t mask = 0x20 | 0x10; + if ( (old ^ data) & mask ) + { + if ( (data & mask) == mask ) t90_start_timer4(); + else t90_stop_timer4(); } - logerror("Read from unimplemented SFR at %04X\n", T90_IOBASE + offset); + m_trun = data; +} + +void tlcs90_device::intel_w(uint8_t data) +{ + m_irq_mask &= ~( (1 << INTT2 ) | + (1 << INTT3 ) | + (1 << INTT4 ) | + (1 << INT1 ) | + (1 << INTT5 ) | + (1 << INT2 ) | + (1 << INTRX ) | + (1 << INTTX ) ); + + m_irq_mask |= ((data & 0x80) ? (1 << INTT2 ) : 0) | + ((data & 0x40) ? (1 << INTT3 ) : 0) | + ((data & 0x20) ? (1 << INTT4 ) : 0) | + ((data & 0x10) ? (1 << INT1 ) : 0) | + ((data & 0x08) ? (1 << INTT5 ) : 0) | + ((data & 0x04) ? (1 << INT2 ) : 0) | + ((data & 0x02) ? (1 << INTRX ) : 0) | + ((data & 0x01) ? (1 << INTTX ) : 0) ; +} + +void tlcs90_device::inteh_w(uint8_t data) +{ + m_irq_mask &= ~( (1 << INT0 ) | + (1 << INTT0) | + (1 << INTT1) ); + + m_irq_mask |= ((data & 0x04) ? (1 << INT0 ) : 0) | + ((data & 0x02) ? (1 << INTT0) : 0) | + ((data & 0x01) ? (1 << INTT1) : 0) ; +} + +void tlcs90_device::irf_clear_w(uint8_t data) +{ + if (data >= int(INTSWI) + 2 && data < int(INTMAX) + 2) + clear_irq(data - 2); +} + +uint8_t tlcs90_device::bx_r() +{ + return 0xf0 | (m_ixbase >> 16); +} + +void tlcs90_device::bx_w(uint8_t data) +{ + m_ixbase = (data & 0xf) << 16; +} + +uint8_t tlcs90_device::by_r() +{ + return 0xf0 | (m_iybase >> 16); +} + +void tlcs90_device::by_w(uint8_t data) +{ + m_iybase = (data & 0xf) << 16; +} + +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_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_prvpc.w.l, data, iobase + offset); +} + void tlcs90_device::t90_start_timer(int i) { int prescaler; @@ -2389,7 +2818,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() @@ -2411,14 +2840,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() @@ -2445,6 +2874,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] ) @@ -2472,7 +2902,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; @@ -2514,224 +2944,9 @@ TIMER_CALLBACK_MEMBER( tlcs90_device::t90_timer4_callback ) } } -WRITE8_MEMBER( tlcs90_device::t90_internal_registers_w ) -{ - uint8_t out_mask; - - switch ( T90_IOBASE + offset ) - { - case T90_TMOD: - m_tmod = data; - break; - - case T90_TCLK: - m_tclk = data; - break; - - case T90_TREG0: - m_treg_8bit[0] = data; - break; - - case T90_TREG1: - m_treg_8bit[1] = data; - break; - - case T90_TREG2: - m_treg_8bit[2] = data; - break; - - case T90_TREG3: - m_treg_8bit[3] = data; - break; - - case T90_T4MOD: - m_t4mod = data; - break; - - case T90_TREG4L: - m_treg_16bit[0] = (m_treg_16bit[0] & 0xff00) | data; - break; - - case T90_TREG4H: - m_treg_16bit[0] = (m_treg_16bit[0] & 0x00ff) | (data << 8); - break; - - case T90_TREG5L: - m_treg_16bit[1] = (m_treg_16bit[1] & 0xff00) | data; - break; - - case T90_TREG5H: - m_treg_16bit[1] = (m_treg_16bit[1] & 0x00ff) | (data << 8); - break; - - case T90_TRUN: - { - int i; - uint8_t mask; - uint8_t old = m_trun; - // Timers 0-3 - for (i = 0; i < 4; i++) - { - mask = 0x20 | (1 << i); - if ( (old ^ data) & mask ) // if timer bit or prescaler bit changed - { - if ( (data & mask) == mask ) t90_start_timer(i); - else t90_stop_timer(i); - } - } - - // Timer 4 - mask = 0x20 | 0x10; - if ( (old ^ data) & mask ) - { - if ( (data & mask) == mask ) t90_start_timer4(); - else t90_stop_timer4(); - } - - m_trun = data; - break; - } - - case T90_INTEL: - m_irq_mask &= ~( (1 << INTT2 ) | - (1 << INTT3 ) | - (1 << INTT4 ) | - (1 << INT1 ) | - (1 << INTT5 ) | - (1 << INT2 ) | - (1 << INTRX ) | - (1 << INTTX ) ); - - m_irq_mask |= ((data & 0x80) ? (1 << INTT2 ) : 0) | - ((data & 0x40) ? (1 << INTT3 ) : 0) | - ((data & 0x20) ? (1 << INTT4 ) : 0) | - ((data & 0x10) ? (1 << INT1 ) : 0) | - ((data & 0x08) ? (1 << INTT5 ) : 0) | - ((data & 0x04) ? (1 << INT2 ) : 0) | - ((data & 0x02) ? (1 << INTRX ) : 0) | - ((data & 0x01) ? (1 << INTTX ) : 0) ; - break; - - case T90_INTEH: - m_irq_mask &= ~( (1 << INT0 ) | - (1 << INTT0) | - (1 << INTT1) ); - - m_irq_mask |= ((data & 0x04) ? (1 << INT0 ) : 0) | - ((data & 0x02) ? (1 << INTT0) : 0) | - ((data & 0x01) ? (1 << INTT1) : 0) ; - break; - - case T90_IRFH: - if (data >= int(INTSWI) + 2 && data < int(INTMAX) + 2) - clear_irq(data - 2); - break; - - case T90_P3: - m_port_latch[3] = data & 0x6c; - m_port_write_cb[3](m_port_latch[3]); - break; - - case T90_P4: - m_port_latch[4] = data & 0x0f; - out_mask = ~m_p4cr & 0x0f; - if (out_mask) - { - m_port_write_cb[4](m_port_latch[4] & out_mask); - } - break; - - case T90_P6: - m_port_latch[6] = data & 0x0f; - out_mask = m_p67cr & 0x0f; - switch (m_smmod & 0x03) - { - case 1: - data &= ~0x01; - // add TO1 here - break; - case 2: - case 3: - data &= ~0x0f; - // add M0 here - break; - } - - if (out_mask) - { - m_port_write_cb[6](m_port_latch[6] & out_mask); - } - break; - - case T90_P7: - m_port_latch[7] = data & 0x0f; - out_mask = m_p67cr >> 4; - switch ((m_smmod >> 4) & 0x03) - { - case 1: - data &= ~0x01; - // add TO3 here - break; - case 2: - case 3: - data &= ~0x0f; - // add M1 here - break; - } - - if (out_mask) - { - m_port_write_cb[7](m_port_latch[7] & out_mask); - } - break; - - case T90_P8: - m_port_latch[8] = data & 0x0f; - out_mask = ~m_p8cr & 0x08; - if (out_mask) - { - m_port_write_cb[8](m_port_latch[8] & out_mask); - } - break; - - case T90_P4CR: - m_p4cr = data; - break; - - case T90_P67CR: - m_p67cr = data; - break; - - case T90_P8CR: - m_p8cr = data; - break; - - case T90_SMMOD: - m_smmod = data; - break; - - case T90_BX: - m_ixbase = (data & 0xf) << 16; - break; - - case T90_BY: - m_iybase = (data & 0xf) << 16; - break; - - default: - logerror("Write to unimplemented SFR at %04X\n", T90_IOBASE + offset); - break; - } -} - void tlcs90_device::device_start() { - for (auto &cb : m_port_read_cb) - cb.resolve_safe(0xff); - for (auto &cb : m_port_write_cb) - cb.resolve_safe(); - save_item(NAME(m_prvpc.w.l)); save_item(NAME(m_pc.w.l)); save_item(NAME(m_sp.w.l)); @@ -2753,6 +2968,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)); @@ -2829,9 +3046,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"); @@ -2848,10 +3065,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); @@ -2877,7 +3094,32 @@ void tlcs90_device::state_string_export(const device_state_entry &entry, std::st } } -std::unique_ptr<util::disasm_interface> tlcs90_device::create_disassembler() +std::unique_ptr<util::disasm_interface> tmp90840_device::create_disassembler() +{ + return std::make_unique<tmp90840_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> tmp90841_device::create_disassembler() +{ + return std::make_unique<tmp90840_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> tmp90845_device::create_disassembler() +{ + return std::make_unique<tmp90840_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> tmp91640_device::create_disassembler() +{ + return std::make_unique<tmp90840_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> tmp91641_device::create_disassembler() +{ + return std::make_unique<tmp90840_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> tmp90ph44_device::create_disassembler() { - return std::make_unique<tlcs90_disassembler>(); + return std::make_unique<tmp90844_disassembler>(); } |