From 9c36794ded21e8869b50041981676b69f4a64412 Mon Sep 17 00:00:00 2001 From: AJR Date: Thu, 18 Jun 2020 18:13:31 -0400 Subject: tlcs900: Split derived types into separate files; no need for separate 8-bit and 16-bit maps now (nw) --- scripts/src/cpu.lua | 4 + src/devices/cpu/tlcs900/tlcs900.cpp | 2142 --------------------------------- src/devices/cpu/tlcs900/tlcs900.h | 185 --- src/devices/cpu/tlcs900/tmp95c061.cpp | 1022 ++++++++++++++++ src/devices/cpu/tlcs900/tmp95c061.h | 96 ++ src/devices/cpu/tlcs900/tmp95c063.cpp | 1129 +++++++++++++++++ src/devices/cpu/tlcs900/tmp95c063.h | 112 ++ src/mame/drivers/ngp.cpp | 2 +- src/mame/drivers/taitopjc.cpp | 2 +- src/mame/drivers/taitotz.cpp | 2 +- 10 files changed, 2366 insertions(+), 2330 deletions(-) create mode 100644 src/devices/cpu/tlcs900/tmp95c061.cpp create mode 100644 src/devices/cpu/tlcs900/tmp95c061.h create mode 100644 src/devices/cpu/tlcs900/tmp95c063.cpp create mode 100644 src/devices/cpu/tlcs900/tmp95c063.h diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 825f63b7c42..8dd9849b2f6 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -2570,6 +2570,10 @@ if (CPUS["TLCS900"]~=null) then MAME_DIR .. "src/devices/cpu/tlcs900/tlcs900.cpp", MAME_DIR .. "src/devices/cpu/tlcs900/tlcs900.h", MAME_DIR .. "src/devices/cpu/tlcs900/900tbl.hxx", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.cpp", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c061.h", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c063.cpp", + MAME_DIR .. "src/devices/cpu/tlcs900/tmp95c063.h", } end diff --git a/src/devices/cpu/tlcs900/tlcs900.cpp b/src/devices/cpu/tlcs900/tlcs900.cpp index 1e014565a63..a0f9d67d597 100644 --- a/src/devices/cpu/tlcs900/tlcs900.cpp +++ b/src/devices/cpu/tlcs900/tlcs900.cpp @@ -18,33 +18,6 @@ TODO: #include "emu.h" #include "tlcs900.h" #include "dasm900.h" -#include "debugger.h" - - -DEFINE_DEVICE_TYPE(TMP95C061, tmp95c061_device, "tmp95c061", "Toshiba TMP95C061") -DEFINE_DEVICE_TYPE(TMP95C063, tmp95c063_device, "tmp95c063", "Toshiba TMP95C063") - - -void tmp95c061_device::tmp95c061_mem8(address_map &map) -{ - map(0x000000, 0x00007f).rw(FUNC(tmp95c061_device::internal_r), FUNC(tmp95c061_device::internal_w)); -} - -void tmp95c061_device::tmp95c061_mem16(address_map &map) -{ - map(0x000000, 0x00007f).rw(FUNC(tmp95c061_device::internal_r), FUNC(tmp95c061_device::internal_w)); -} - - -void tmp95c063_device::tmp95c063_mem8(address_map &map) -{ - map(0x000000, 0x00009f).rw(FUNC(tmp95c063_device::internal_r), FUNC(tmp95c063_device::internal_w)); -} - -void tmp95c063_device::tmp95c063_mem16(address_map &map) -{ - map(0x000000, 0x00009f).rw(FUNC(tmp95c063_device::internal_r), FUNC(tmp95c063_device::internal_w)); -} tlcs900h_device::tlcs900h_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : @@ -53,27 +26,6 @@ tlcs900h_device::tlcs900h_device(const machine_config &mconfig, device_type type { } -tmp95c061_device::tmp95c061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - tlcs900h_device(mconfig, TMP95C061, tag, owner, clock), - m_port1_read(*this), - m_port1_write(*this), - m_port2_write(*this), - m_port5_read(*this), - m_port5_write(*this), - m_port6_read(*this), - m_port6_write(*this), - m_port7_read(*this), - m_port7_write(*this), - m_port8_read(*this), - m_port8_write(*this), - m_port9_read(*this), - m_porta_read(*this), - m_porta_write(*this), - m_portb_read(*this), - m_portb_write(*this) -{ -} - device_memory_interface::space_config_vector tlcs900h_device::memory_space_config() const { return space_config_vector { @@ -81,70 +33,6 @@ device_memory_interface::space_config_vector tlcs900h_device::memory_space_confi }; } -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void tmp95c061_device::device_config_complete() -{ - if (m_am8_16 == 0) - { - m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp95c061_device::tmp95c061_mem16), this)); - } - else - { - m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp95c061_device::tmp95c061_mem8), this)); - } -} - -tmp95c063_device::tmp95c063_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - tlcs900h_device(mconfig, TMP95C063, tag, owner, clock), - m_port1_read(*this), - m_port1_write(*this), - m_port2_write(*this), - m_port5_read(*this), - m_port5_write(*this), - m_port6_read(*this), - m_port6_write(*this), - m_port7_read(*this), - m_port7_write(*this), - m_port8_read(*this), - m_port8_write(*this), - m_port9_read(*this), - m_port9_write(*this), - m_porta_read(*this), - m_porta_write(*this), - m_portb_read(*this), - m_portb_write(*this), - m_portc_read(*this), - m_portd_read(*this), - m_portd_write(*this), - m_porte_read(*this), - m_porte_write(*this), - m_an_read(*this) -{ -} - -//------------------------------------------------- -// device_config_complete - perform any -// operations now that the configuration is -// complete -//------------------------------------------------- - -void tmp95c063_device::device_config_complete() -{ - if (m_am8_16 == 0) - { - m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp95c063_device::tmp95c063_mem16), this)); - } - else - { - m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp95c063_device::tmp95c063_mem8), this)); - } -} - std::unique_ptr tlcs900h_device::create_disassembler() { @@ -152,116 +40,6 @@ std::unique_ptr tlcs900h_device::create_disassembler() } - -/* Internal register defines */ -#define TMP95C061_P1 0x01 -#define TMP95C061_P1CR 0x02 -#define TMP95C061_P2 0x06 -#define TMP95C061_P2FC 0x09 -#define TMP95C061_P5 0x0d -#define TMP95C061_P5CR 0x10 -#define TMP95C061_P5FC 0x11 -#define TMP95C061_P6 0x12 -#define TMP95C061_P7 0x13 -#define TMP95C061_P6FC 0x15 -#define TMP95C061_P7CR 0x16 -#define TMP95C061_P7FC 0x17 -#define TMP95C061_P8 0x18 -#define TMP95C061_P9 0x19 -#define TMP95C061_P8CR 0x1a -#define TMP95C061_P8FC 0x1b -#define TMP95C061_PA 0x1e -#define TMP95C061_PB 0x1f -#define TMP95C061_TRUN 0x20 -#define TMP95C061_TREG0 0x22 -#define TMP95C061_TREG1 0x23 -#define TMP95C061_T01MOD 0x24 -#define TMP95C061_TFFCR 0x25 -#define TMP95C061_TREG2 0x26 -#define TMP95C061_TREG3 0x27 -#define TMP95C061_T23MOD 0x28 -#define TMP95C061_TRDC 0x29 -#define TMP95C061_PACR 0x2c -#define TMP95C061_PAFC 0x2d -#define TMP95C061_PBCR 0x2e -#define TMP95C061_PBFC 0x2f -#define TMP95C061_TREG4L 0x30 -#define TMP95C061_TREG4H 0x31 -#define TMP95C061_TREG5L 0x32 -#define TMP95C061_TREG5H 0x33 -#define TMP95C061_CAP1L 0x34 -#define TMP95C061_CAP1H 0x35 -#define TMP95C061_CAP2L 0x36 -#define TMP95C061_CAP2H 0x37 -#define TMP95C061_T4MOD 0x38 -#define TMP95C061_T4FFCR 0x39 -#define TMP95C061_T45CR 0x3a -#define TMP95C061_MSAR0 0x3c -#define TMP95C061_MAMR0 0x3d -#define TMP95C061_MSAR1 0x3e -#define TMP95C061_MAMR1 0x3f -#define TMP95C061_TREG6L 0x40 -#define TMP95C061_TREG6H 0x41 -#define TMP95C061_TREG7L 0x42 -#define TMP95C061_TREG7H 0x43 -#define TMP95C061_CAP3L 0x44 -#define TMP95C061_CAP3H 0x45 -#define TMP95C061_CAP4L 0x46 -#define TMP95C061_CAP4H 0x47 -#define TMP95C061_T5MOD 0x48 -#define TMP95C061_T5FFCR 0x49 -#define TMP95C061_PG0REG 0x4c -#define TMP95C061_PG1REG 0x4d -#define TMP95C061_PG01CR 0x4e -#define TMP95C061_SC0BUF 0x50 -#define TMP95C061_SC0CR 0x51 -#define TMP95C061_SC0MOD 0x52 -#define TMP95C061_BR0CR 0x53 -#define TMP95C061_SC1BUF 0x54 -#define TMP95C061_SC1CR 0x55 -#define TMP95C061_SC1MOD 0x56 -#define TMP95C061_BR1CR 0x57 -#define TMP95C061_ODE 0x58 -#define TMP95C061_DREFCR 0x5a -#define TMP95C061_DMEMCR 0x5b -#define TMP95C061_MSAR2 0x5c -#define TMP95C061_MAMR2 0x5d -#define TMP95C061_MSAR3 0x5e -#define TMP95C061_MAMR3 0x5f -#define TMP95C061_ADREG0L 0x60 -#define TMP95C061_ADREG0H 0x61 -#define TMP95C061_ADREG1L 0x62 -#define TMP95C061_ADREG1H 0x63 -#define TMP95C061_ADREG2L 0x64 -#define TMP95C061_ADREG2H 0x65 -#define TMP95C061_ADREG3L 0x66 -#define TMP95C061_ADREG3H 0x67 -#define TMP95C061_B0CS 0x68 -#define TMP95C061_B1CS 0x69 -#define TMP95C061_B2CS 0x6a -#define TMP95C061_B3CS 0x6b -#define TMP95C061_BEXCS 0x6c -#define TMP95C061_ADMOD 0x6d -#define TMP95C061_WDMOD 0x6e -#define TMP95C061_WDCR 0x6f -#define TMP95C061_INTE0AD 0x70 -#define TMP95C061_INTE45 0x71 -#define TMP95C061_INTE67 0x72 -#define TMP95C061_INTET10 0x73 -#define TMP95C061_INTET32 0x74 -#define TMP95C061_INTET54 0x75 -#define TMP95C061_INTET76 0x76 -#define TMP95C061_INTES0 0x77 -#define TMP95C061_INTES1 0x78 -#define TMP95C061_INTETC10 0x79 -#define TMP95C061_INTETC32 0x7a -#define TMP95C061_IIMC 0x7b -#define TMP95C061_DMA0V 0x7c -#define TMP95C061_DMA1V 0x7d -#define TMP95C061_DMA2V 0x7e -#define TMP95C061_DMA3V 0x7f - - /* Flag defines */ #define FLAG_CF 0x01 #define FLAG_NF 0x02 @@ -411,630 +189,10 @@ void tlcs900h_device::state_string_export(const device_state_entry &entry, std:: } } -void tmp95c061_device::device_start() -{ - tlcs900h_device::device_start(); - - save_item( NAME(m_to1) ); - save_item( NAME(m_to3) ); - - m_port1_read.resolve_safe(0); - m_port1_write.resolve_safe(); - m_port2_write.resolve_safe(); - m_port5_read.resolve_safe(0); - m_port5_write.resolve_safe(); - m_port6_read.resolve_safe(0); - m_port6_write.resolve_safe(); - m_port7_read.resolve_safe(0); - m_port7_write.resolve_safe(); - m_port8_read.resolve_safe(0); - m_port8_write.resolve_safe(); - m_port9_read.resolve_safe(0); - m_porta_read.resolve_safe(0); - m_porta_write.resolve_safe(); - m_portb_read.resolve_safe(0); - m_portb_write.resolve_safe(); -} - -void tmp95c061_device::device_reset() -{ - int i; - - m_to1 = 0; - m_to3 = 0; - - m_pc.b.l = RDMEM( 0xFFFF00 ); - m_pc.b.h = RDMEM( 0xFFFF01 ); - m_pc.b.h2 = RDMEM( 0xFFFF02 ); - m_pc.b.h3 = 0; - /* system mode, iff set to 111, max mode, register bank 0 */ - m_sr.d = 0xF800; - m_regbank = 0; - m_xssp.d = 0x0100; - m_halted = 0; - m_check_irqs = 0; - m_ad_cycles_left = 0; - m_nmi_state = CLEAR_LINE; - m_timer_pre = 0; - m_timer_change[0] = 0; - m_timer_change[1] = 0; - m_timer_change[2] = 0; - m_timer_change[3] = 0; - - memset(m_reg, 0x00, sizeof(m_reg)); - - m_reg[TMP95C061_P1] = 0x00; - m_reg[TMP95C061_P1CR] = 0x00; - m_reg[TMP95C061_P2] = 0xff; - m_reg[TMP95C061_P2FC] = 0x00; - m_reg[TMP95C061_P5] = 0x3d; - m_reg[TMP95C061_P5CR] = 0x00; - m_reg[TMP95C061_P5FC] = 0x00; - m_reg[TMP95C061_P6] = 0x3b; - m_reg[TMP95C061_P6FC] = 0x00; - m_reg[TMP95C061_P7] = 0xff; - m_reg[TMP95C061_P7CR] = 0x00; - m_reg[TMP95C061_P7FC] = 0x00; - m_reg[TMP95C061_P8] = 0x3f; - m_reg[TMP95C061_P8CR] = 0x00; - m_reg[TMP95C061_P8FC] = 0x00; - m_reg[TMP95C061_PA] = 0x0f; - m_reg[TMP95C061_PACR] = 0x0c; // HACK ngpc needs this but should be zero - m_reg[TMP95C061_PAFC] = 0x0c; // HACK ngpc needs this but should be zero - m_reg[TMP95C061_PB] = 0xff; - m_reg[TMP95C061_PBCR] = 0x00; - m_reg[TMP95C061_PBFC] = 0x00; - m_reg[TMP95C061_MSAR0] = 0xff; - m_reg[TMP95C061_MSAR1] = 0xff; - m_reg[TMP95C061_MSAR2] = 0xff; - m_reg[TMP95C061_MSAR3] = 0xff; - m_reg[TMP95C061_MAMR0] = 0xff; - m_reg[TMP95C061_MAMR1] = 0xff; - m_reg[TMP95C061_MAMR2] = 0xff; - m_reg[TMP95C061_MAMR3] = 0xff; - m_reg[TMP95C061_DREFCR] = 0x00; - m_reg[TMP95C061_DMEMCR] = 0x80; - m_reg[TMP95C061_T01MOD] = 0x00; - m_reg[TMP95C061_T23MOD] = 0x00; - m_reg[TMP95C061_TFFCR] = 0x00; - m_reg[TMP95C061_TRUN] = 0x00; - m_reg[TMP95C061_TRDC] = 0x00; - m_reg[TMP95C061_T4MOD] = 0x20; - m_reg[TMP95C061_T4FFCR] = 0x00; - m_reg[TMP95C061_T5MOD] = 0x20; - m_reg[TMP95C061_T5FFCR] = 0x00; - m_reg[TMP95C061_T45CR] = 0x00; - m_reg[TMP95C061_PG01CR] = 0x00; - m_reg[TMP95C061_PG0REG] = 0x00; - m_reg[TMP95C061_PG1REG] = 0x00; - m_reg[TMP95C061_SC0MOD] = 0x00; - m_reg[TMP95C061_SC0CR] = 0x00; - m_reg[TMP95C061_BR0CR] = 0x00; - m_reg[TMP95C061_SC1MOD] = 0x00; - m_reg[TMP95C061_SC1CR] = 0x00; - m_reg[TMP95C061_BR1CR] = 0x00; - m_reg[TMP95C061_P8FC] = 0x00; - m_reg[TMP95C061_ODE] = 0x00; - m_reg[TMP95C061_ADMOD] = 0x00; - m_reg[TMP95C061_ADREG0L] = 0x3f; - m_reg[TMP95C061_ADREG1L] = 0x3f; - m_reg[TMP95C061_ADREG2L] = 0x3f; - m_reg[TMP95C061_ADREG3L] = 0x3f; - m_reg[TMP95C061_WDMOD] = 0x80; - - for ( i = 0; i < TLCS900_NUM_INPUTS; i++ ) - { - m_level[i] = CLEAR_LINE; - } - m_prefetch_clear = true; -} - #include "900tbl.hxx" -#define TMP95C061_NUM_MASKABLE_IRQS 22 -static const struct { - uint8_t reg; - uint8_t iff; - uint8_t vector; -} tmp95c061_irq_vector_map[TMP95C061_NUM_MASKABLE_IRQS] = -{ - { TMP95C061_INTETC32, 0x80, 0x80 }, /* INTTC3 */ - { TMP95C061_INTETC32, 0x08, 0x7c }, /* INTTC2 */ - { TMP95C061_INTETC10, 0x80, 0x78 }, /* INTTC1 */ - { TMP95C061_INTETC10, 0x08, 0x74 }, /* INTTC0 */ - { TMP95C061_INTE0AD, 0x80, 0x70 }, /* INTAD */ - { TMP95C061_INTES1, 0x80, 0x6c }, /* INTTX1 */ - { TMP95C061_INTES1, 0x08, 0x68 }, /* INTRX1 */ - { TMP95C061_INTES0, 0x80, 0x64 }, /* INTTX0 */ - { TMP95C061_INTES0, 0x08, 0x60 }, /* INTRX0 */ - { TMP95C061_INTET76, 0x80, 0x5c }, /* INTTR7 */ - { TMP95C061_INTET76, 0x08, 0x58 }, /* INTTR6 */ - { TMP95C061_INTET54, 0x80, 0x54 }, /* INTTR5 */ - { TMP95C061_INTET54, 0x08, 0x50 }, /* INTTR4 */ - { TMP95C061_INTET32, 0x80, 0x4c }, /* INTT3 */ - { TMP95C061_INTET32, 0x08, 0x48 }, /* INTT2 */ - { TMP95C061_INTET10, 0x80, 0x44 }, /* INTT1 */ - { TMP95C061_INTET10, 0x08, 0x40 }, /* INTT0 */ - /* 0x3c - reserved */ - { TMP95C061_INTE67, 0x80, 0x38 }, /* INT7 */ - { TMP95C061_INTE67, 0x08, 0x34 }, /* INT6 */ - { TMP95C061_INTE45, 0x80, 0x30 }, /* INT5 */ - { TMP95C061_INTE45, 0x08, 0x2c }, /* INT4 */ - { TMP95C061_INTE0AD, 0x08, 0x28 } /* INT0 */ -}; - - -int tmp95c061_device::tlcs900_process_hdma( int channel ) -{ - uint8_t vector = ( m_reg[0x7c + channel] & 0x1f ) << 2; - - /* Check if any HDMA actions should be performed */ - if ( vector >= 0x28 && vector != 0x3C && vector < 0x74 ) - { - int irq = 0; - - while( irq < TMP95C061_NUM_MASKABLE_IRQS && tmp95c061_irq_vector_map[irq].vector != vector ) - irq++; - - /* Check if our interrupt flip-flop is set */ - if ( irq < TMP95C061_NUM_MASKABLE_IRQS && m_reg[tmp95c061_irq_vector_map[irq].reg] & tmp95c061_irq_vector_map[irq].iff ) - { - switch( m_dmam[channel].b.l & 0x1f ) - { - case 0x00: - WRMEM( m_dmad[channel].d, RDMEM( m_dmas[channel].d ) ); - m_dmad[channel].d += 1; - m_cycles += 8; - break; - case 0x01: - WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_dmad[channel].d += 2; - m_cycles += 8; - break; - case 0x02: - WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); - m_dmad[channel].d += 4; - m_cycles += 12; - break; - case 0x04: - WRMEM( m_dmad[channel].d, RDMEM( m_dmas[channel].d ) ); - m_dmad[channel].d -= 1; - m_cycles += 8; - break; - case 0x05: - WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_dmad[channel].d -= 2; - m_cycles += 8; - break; - case 0x06: - WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); - m_dmad[channel].d -= 4; - m_cycles += 12; - break; - case 0x08: - WRMEM( m_dmad[channel].d, RDMEM( m_dmas[channel].d ) ); - m_dmas[channel].d += 1; - m_cycles += 8; - break; - case 0x09: - WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_dmas[channel].d += 2; - m_cycles += 8; - break; - case 0x0a: - WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); - m_dmas[channel].d += 4; - m_cycles += 12; - break; - case 0x0c: - WRMEM( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_dmas[channel].d -= 1; - m_cycles += 8; - break; - case 0x0d: - WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_dmas[channel].d -= 2; - m_cycles += 8; - break; - case 0x0e: - WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); - m_dmas[channel].d -= 4; - m_cycles += 12; - break; - case 0x10: - WRMEM( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_cycles += 8; - break; - case 0x11: - WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); - m_cycles += 8; - break; - case 0x12: - WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); - m_cycles += 12; - break; - case 0x14: - m_dmas[channel].d += 1; - m_cycles += 5; - break; - } - - m_dmac[channel].w.l -= 1; - - if ( m_dmac[channel].w.l == 0 ) - { - m_reg[0x7c + channel] = 0; - switch( channel ) - { - case 0: - m_reg[TMP95C061_INTETC10] |= 0x08; - break; - case 1: - m_reg[TMP95C061_INTETC10] |= 0x80; - break; - case 2: - m_reg[TMP95C061_INTETC32] |= 0x08; - break; - case 3: - m_reg[TMP95C061_INTETC32] |= 0x80; - break; - } - } - - /* Clear the interrupt flip-flop */ - m_reg[tmp95c061_irq_vector_map[irq].reg] &= ~tmp95c061_irq_vector_map[irq].iff; - - return 1; - } - } - return 0; -} - - -void tmp95c061_device::tlcs900_check_hdma() -{ - /* HDMA can only be performed if interrupts are allowed */ - if ( ( m_sr.b.h & 0x70 ) != 0x70 ) - { - if ( ! tlcs900_process_hdma( 0 ) ) - { - if ( ! tlcs900_process_hdma( 1 ) ) - { - if ( ! tlcs900_process_hdma( 2 ) ) - { - tlcs900_process_hdma( 3 ); - } - } - } - } -} - - -void tmp95c061_device::tlcs900_check_irqs() -{ - int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - int level = 0; - int irq = -1; - int i; - - /* Check for NMI */ - if ( m_nmi_state == ASSERT_LINE ) - { - m_xssp.d -= 4; - WRMEML( m_xssp.d, m_pc.d ); - m_xssp.d -= 2; - WRMEMW( m_xssp.d, m_sr.w.l ); - m_pc.d = RDMEML( 0xffff00 + 0x20 ); - m_cycles += 18; - m_prefetch_clear = true; - - m_halted = 0; - - m_nmi_state = CLEAR_LINE; - - return; - } - - /* Check regular irqs */ - for( i = 0; i < TMP95C061_NUM_MASKABLE_IRQS; i++ ) - { - if ( m_reg[tmp95c061_irq_vector_map[i].reg] & tmp95c061_irq_vector_map[i].iff ) - { - switch( tmp95c061_irq_vector_map[i].iff ) - { - case 0x80: - irq_vectors[ ( m_reg[ tmp95c061_irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i; - break; - case 0x08: - irq_vectors[ m_reg[ tmp95c061_irq_vector_map[i].reg ] & 0x07 ] = i; - break; - } - } - } - - /* Check highest allowed priority irq */ - for ( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) - { - if ( irq_vectors[i] >= 0 ) - { - irq = irq_vectors[i]; - level = i + 1; - } - } - - /* Take irq */ - if ( irq >= 0 ) - { - uint8_t vector = tmp95c061_irq_vector_map[irq].vector; - - m_xssp.d -= 4; - WRMEML( m_xssp.d, m_pc.d ); - m_xssp.d -= 2; - WRMEMW( m_xssp.d, m_sr.w.l ); - - /* Mask off any lower priority interrupts */ - m_sr.b.h = ( m_sr.b.h & 0x8f ) | ( level << 4 ); - - m_pc.d = RDMEML( 0xffff00 + vector ); - m_cycles += 18; - m_prefetch_clear = true; - - m_halted = 0; - - /* Clear taken IRQ */ - m_reg[ tmp95c061_irq_vector_map[irq].reg ] &= ~ tmp95c061_irq_vector_map[irq].iff; - } -} - - -void tmp95c061_device::tlcs900_handle_ad() -{ - if ( m_ad_cycles_left > 0 ) - { - m_ad_cycles_left -= m_cycles; - if ( m_ad_cycles_left <= 0 ) - { - /* Store A/D converted value */ - switch( m_reg[TMP95C061_ADMOD] & 0x03 ) - { - case 0x00: /* AN0 */ - m_reg[TMP95C061_ADREG0L] |= 0xc0; - m_reg[TMP95C061_ADREG0H] = 0xff; - break; - case 0x01: /* AN1 */ - case 0x02: /* AN2 */ - case 0x03: /* AN3 */ - break; - } - - /* Clear BUSY flag, set END flag */ - m_reg[TMP95C061_ADMOD] &= ~ 0x40; - m_reg[TMP95C061_ADMOD] |= 0x80; - - m_reg[TMP95C061_INTE0AD] |= 0x80; - m_check_irqs = 1; - } - } -} - - -enum ff_change -{ - FF_CLEAR, - FF_SET, - FF_INVERT -}; - - -void tmp95c061_device::tlcs900_change_tff( int which, int change ) -{ - switch( which ) - { - case 1: - switch( change ) - { - case FF_CLEAR: - m_to1 = 0; - break; - case FF_SET: - m_to1 = 1; - break; - case FF_INVERT: - m_to1 ^= 1; - break; - } - break; - - case 3: - switch( change ) - { - case FF_CLEAR: - m_to3 = 0; - break; - case FF_SET: - m_to3 = 1; - break; - case FF_INVERT: - m_to3 ^= 1; - break; - } - break; - } - - update_porta(); -} - - -void tmp95c061_device::tlcs900_handle_timers() -{ - uint32_t old_pre = m_timer_pre; - - /* Is the pre-scaler active */ - if ( m_reg[TMP95C061_TRUN] & 0x80 ) - m_timer_pre += m_cycles; - - /* Timer 0 */ - if ( m_reg[TMP95C061_TRUN] & 0x01 ) - { - switch( m_reg[TMP95C061_T01MOD] & 0x03 ) - { - case 0x00: /* TIO */ - break; - case 0x01: /* T1 */ - m_timer_change[0] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T4 */ - m_timer_change[0] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); - break; - case 0x03: /* T16 */ - m_timer_change[0] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - } - - for( ; m_timer_change[0] > 0; m_timer_change[0]-- ) - { -//printf("timer0 = %02x, TREG0 = %02x\n", m_timer[0], m_reg[TREG0] ); - m_timer[0] += 1; - if ( m_timer[0] == m_reg[TMP95C061_TREG0] ) - { - if ( ( m_reg[TMP95C061_T01MOD] & 0x0c ) == 0x00 ) - { - m_timer_change[1] += 1; - } - - /* In 16bit timer mode the timer should not be reset */ - if ( ( m_reg[TMP95C061_T01MOD] & 0xc0 ) != 0x40 ) - { - m_timer[0] = 0; - m_reg[TMP95C061_INTET10] |= 0x08; - } - } - } - } - - /* Timer 1 */ - if ( m_reg[TMP95C061_TRUN] & 0x02 ) - { - switch( ( m_reg[TMP95C061_T01MOD] >> 2 ) & 0x03 ) - { - case 0x00: /* TO0TRG */ - break; - case 0x01: /* T1 */ - m_timer_change[1] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T16 */ - m_timer_change[1] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - case 0x03: /* T256 */ - m_timer_change[1] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); - break; - } - - for( ; m_timer_change[1] > 0; m_timer_change[1]-- ) - { - m_timer[1] += 1; - if ( m_timer[1] == m_reg[TMP95C061_TREG1] ) - { - m_timer[1] = 0; - m_reg[TMP95C061_INTET10] |= 0x80; - - if ( m_reg[TMP95C061_TFFCR] & 0x02 ) - { - tlcs900_change_tff( 1, FF_INVERT ); - } - - /* In 16bit timer mode also reset timer 0 */ - if ( ( m_reg[TMP95C061_T01MOD] & 0xc0 ) == 0x40 ) - { - m_timer[0] = 0; - } - } - } - } - - /* Timer 2 */ - if ( m_reg[TMP95C061_TRUN] & 0x04 ) - { - switch( m_reg[TMP95C061_T23MOD] & 0x03 ) - { - case 0x00: /* invalid */ - case 0x01: /* T1 */ - m_timer_change[2] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T4 */ - m_timer_change[2] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); - break; - case 0x03: /* T16 */ - m_timer_change[2] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - } - - for( ; m_timer_change[2] > 0; m_timer_change[2]-- ) - { - m_timer[2] += 1; - if ( m_timer[2] == m_reg[TMP95C061_TREG2] ) - { - if ( ( m_reg[TMP95C061_T23MOD] & 0x0c ) == 0x00 ) - { - m_timer_change[3] += 1; - } - - /* In 16bit timer mode the timer should not be reset */ - if ( ( m_reg[TMP95C061_T23MOD] & 0xc0 ) != 0x40 ) - { - m_timer[2] = 0; - m_reg[TMP95C061_INTET32] |= 0x08; - } - } - } - } - - /* Timer 3 */ - if ( m_reg[TMP95C061_TRUN] & 0x08 ) - { - switch( ( m_reg[TMP95C061_T23MOD] >> 2 ) & 0x03 ) - { - case 0x00: /* TO2TRG */ - break; - case 0x01: /* T1 */ - m_timer_change[3] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T16 */ - m_timer_change[3] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - case 0x03: /* T256 */ - m_timer_change[3] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); - break; - } - - for( ; m_timer_change[3] > 0; m_timer_change[3]-- ) - { - m_timer[3] += 1; - if ( m_timer[3] == m_reg[TMP95C061_TREG3] ) - { - m_timer[3] = 0; - m_reg[TMP95C061_INTET32] |= 0x80; - - if ( m_reg[TMP95C061_TFFCR] & 0x20 ) - { - tlcs900_change_tff( 3, FF_INVERT ); - } - - /* In 16bit timer mode also reset timer 2 */ - if ( ( m_reg[TMP95C061_T23MOD] & 0xc0 ) == 0x40 ) - { - m_timer[2] = 0; - } - } - } - } - - m_timer_pre &= 0xffffff; -} - - void tlcs900h_device::execute_run() { do @@ -1075,1303 +233,3 @@ void tlcs900h_device::execute_run() m_icount -= m_cycles; } while ( m_icount > 0 ); } - - -void tmp95c061_device::execute_set_input(int input, int level) -{ - switch( input ) - { - case INPUT_LINE_NMI: - case TLCS900_NMI: - if ( m_level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_nmi_state = level; - } - m_level[TLCS900_NMI] = level; - break; - - case TLCS900_INTWD: - break; - - case TLCS900_INT0: - /* Is INT0 functionality enabled? */ - if ( m_reg[TMP95C061_IIMC] & 0x04 ) - { - if ( m_reg[TMP95C061_IIMC] & 0x02 ) - { - /* Rising edge detect */ - if ( m_level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE ) - { - /* Leave HALT state */ - m_halted = 0; - m_reg[TMP95C061_INTE0AD] |= 0x08; - } - } - else - { - /* Level detect */ - if ( level == ASSERT_LINE ) - m_reg[TMP95C061_INTE0AD] |= 0x08; - else - m_reg[TMP95C061_INTE0AD] &= ~ 0x08; - } - } - m_level[TLCS900_INT0] = level; - break; - - case TLCS900_INT4: - if ( ! ( m_reg[TMP95C061_PBCR] & 0x01 ) ) - { - if ( m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_reg[TMP95C061_INTE45] |= 0x08; - } - } - m_level[TLCS900_INT4] = level; - break; - - case TLCS900_INT5: - if ( ! ( m_reg[TMP95C061_PBCR] & 0x02 ) ) - { - if ( m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_reg[TMP95C061_INTE45] |= 0x80; - } - } - m_level[TLCS900_INT5] = level; - break; - - case TLCS900_TIO: /* External timer input for timer 0 */ - if ( ( m_reg[TMP95C061_TRUN] & 0x01 ) && ( m_reg[TMP95C061_T01MOD] & 0x03 ) == 0x00 ) - { - if ( m_level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_timer_change[0] += 1; - } - } - m_level[TLCS900_TIO] = level; - break; - } - m_check_irqs = 1; -} - - -uint8_t tmp95c061_device::internal_r(offs_t offset) -{ - switch (offset) - { - case TMP95C061_P1: m_reg[offset] = m_port1_read(0); break; - case TMP95C061_P5: m_reg[offset] = m_port5_read(0); break; - case TMP95C061_P6: m_reg[offset] = m_port6_read(0); break; - case TMP95C061_P7: m_reg[offset] = m_port7_read(0); break; - case TMP95C061_P8: m_reg[offset] = m_port8_read(0); break; - case TMP95C061_P9: m_reg[offset] = m_port9_read(0); break; - case TMP95C061_PA: m_reg[offset] = m_porta_read(0); break; - case TMP95C061_PB: m_reg[offset] = m_portb_read(0); break; - } - return m_reg[ offset ]; -} - - -void tmp95c061_device::update_porta() -{ - int fc = (m_to1 << 2) | (m_to3 << 3); - - m_porta_write(0, ((fc & m_reg[TMP95C061_PAFC]) | (m_reg[TMP95C061_PA] & ~m_reg[TMP95C061_PAFC])) & m_reg[TMP95C061_PACR], 0xff); -} - -void tmp95c061_device::internal_w(offs_t offset, uint8_t data) -{ - switch ( offset ) - { - case TMP95C061_TRUN: - if ( ! ( data & 0x01 ) ) - { - m_timer[0] = 0; - m_timer_change[0] = 0; - } - if ( ! ( data & 0x02 ) ) - { - m_timer[1] = 0; - m_timer_change[1] = 0; - } - if ( ! ( data & 0x04 ) ) - { - m_timer[2] = 0; - m_timer_change[2] = 0; - } - if ( ! ( data & 0x08 ) ) - { - m_timer[3] = 0; - m_timer_change[3] = 0; - } - if ( ! ( data & 0x10 ) ) - m_timer[4] = 0; - if ( ! ( data & 0x20 ) ) - m_timer[5] = 0; - break; - - case TMP95C061_TFFCR: - switch( data & 0x0c ) - { - case 0x00: - tlcs900_change_tff( 1, FF_INVERT ); - break; - case 0x04: - tlcs900_change_tff( 1, FF_SET ); - break; - case 0x08: - tlcs900_change_tff( 1, FF_CLEAR ); - break; - } - switch( data & 0xc0 ) - { - case 0x00: - tlcs900_change_tff( 3, FF_INVERT ); - break; - case 0x40: - tlcs900_change_tff( 3, FF_SET ); - break; - case 0x80: - tlcs900_change_tff( 3, FF_CLEAR ); - break; - } - break; - case TMP95C061_MSAR0: - case TMP95C061_MAMR0: - case TMP95C061_MSAR1: - case TMP95C061_MAMR1: - break; - - case TMP95C061_SC0BUF: - // Fake finish sending data - m_reg[TMP95C061_INTES0] |= 0x80; - break; - - case TMP95C061_ADMOD: - /* Preserve read-only bits */ - data = ( m_reg[TMP95C061_ADMOD] & 0xc0 ) | ( data & 0x3f ); - - /* Check for A/D request start */ - if ( data & 0x04 ) - { - data &= ~0x04; - data |= 0x40; - m_ad_cycles_left = ( data & 0x08 ) ? 640 : 320; - } - break; - - case TMP95C061_WDMOD: - case TMP95C061_WDCR: - break; - - case TMP95C061_INTE0AD: - case TMP95C061_INTE45: - case TMP95C061_INTE67: - case TMP95C061_INTET10: - case TMP95C061_INTET32: - case TMP95C061_INTET54: - case TMP95C061_INTET76: - case TMP95C061_INTES0: - case TMP95C061_INTES1: - case TMP95C061_INTETC10: - case TMP95C061_INTETC32: - if ( data & 0x80 ) - data = ( data & 0x7f ) | ( m_reg[offset] & 0x80 ); - if ( data & 0x08 ) - data = ( data & 0xf7 ) | ( m_reg[offset] & 0x08 ); - break; - - case TMP95C061_IIMC: - break; - - default: - break; - } - - m_check_irqs = 1; - m_reg[ offset ] = data; - - switch(offset) - { - case TMP95C061_P1: m_port1_write(0, data, 0xff); break; - case TMP95C061_P2: m_port2_write(0, data, 0xff); break; - case TMP95C061_P5: m_port5_write(0, data, 0xff); break; - case TMP95C061_P6: m_port6_write(0, data, 0xff); break; - case TMP95C061_P7: m_port7_write(0, data, 0xff); break; - case TMP95C061_P8: m_port8_write(0, data, 0xff); break; - - case TMP95C061_PA: - case TMP95C061_PACR: - case TMP95C061_PAFC: - update_porta(); - break; - } -} - - - -// Toshiba TMP95C063 - -/* TMP95C063 Internal register defines */ - -#define TMP95C063_P1 0x01 -#define TMP95C063_P1CR 0x04 -#define TMP95C063_P2 0x06 -#define TMP95C063_P2FC 0x09 -#define TMP95C063_P5 0x0d -#define TMP95C063_P5CR 0x10 -#define TMP95C063_P5FC 0x11 -#define TMP95C063_P6 0x12 -#define TMP95C063_P7 0x13 -#define TMP95C063_P6FC 0x15 -#define TMP95C063_P7CR 0x16 -#define TMP95C063_P7FC 0x17 -#define TMP95C063_P8 0x18 -#define TMP95C063_P9 0x19 -#define TMP95C063_P8CR 0x1a -#define TMP95C063_P8FC 0x1b -#define TMP95C063_P9CR 0x1c -#define TMP95C063_P9FC 0x1d -#define TMP95C063_PA 0x1e -#define TMP95C063_PB 0x1f -#define TMP95C063_T8RUN 0x20 -#define TMP95C063_TRDC 0x21 -#define TMP95C063_TREG0 0x22 -#define TMP95C063_TREG1 0x23 -#define TMP95C063_T01MOD 0x24 -#define TMP95C063_T02FFCR 0x25 -#define TMP95C063_TREG2 0x26 -#define TMP95C063_TREG3 0x27 -#define TMP95C063_T23MOD 0x28 -#define TMP95C063_TREG4 0x29 -#define TMP95C063_TREG5 0x2a -#define TMP95C063_T45MOD 0x2b -#define TMP95C063_T46FFCR 0x2c -#define TMP95C063_TREG6 0x2d -#define TMP95C063_TREG7 0x2e -#define TMP95C063_T67MOD 0x2f -#define TMP95C063_TREG8L 0x30 -#define TMP95C063_TREG8H 0x31 -#define TMP95C063_TREG9L 0x32 -#define TMP95C063_TREG9H 0x33 -#define TMP95C063_CAP1L 0x34 -#define TMP95C063_CAP1H 0x35 -#define TMP95C063_CAP2L 0x36 -#define TMP95C063_CAP2H 0x37 -#define TMP95C063_T8MOD 0x38 -#define TMP95C063_T8FFCR 0x39 -#define TMP95C063_T89CR 0x3a -#define TMP95C063_T16RUN 0x3b -#define TMP95C063_TREGAL 0x40 -#define TMP95C063_TREGAH 0x41 -#define TMP95C063_TREGBL 0x42 -#define TMP95C063_TREGBH 0x43 -#define TMP95C063_CAP3L 0x44 -#define TMP95C063_CAP3H 0x45 -#define TMP95C063_CAP4L 0x46 -#define TMP95C063_CAP4H 0x47 -#define TMP95C063_T9MOD 0x48 -#define TMP95C063_T9FFCR 0x49 -#define TMP95C063_DAREG0 0x4a -#define TMP95C063_DAREG1 0x4b -#define TMP95C063_PG0REG 0x4c -#define TMP95C063_PG1REG 0x4d -#define TMP95C063_PG01CR 0x4e -#define TMP95C063_DADRV 0x4f -#define TMP95C063_SC0BUF 0x50 -#define TMP95C063_SC0CR 0x51 -#define TMP95C063_SC0MOD 0x52 -#define TMP95C063_BR0CR 0x53 -#define TMP95C063_SC1BUF 0x54 -#define TMP95C063_SC1CR 0x55 -#define TMP95C063_SC1MOD 0x56 -#define TMP95C063_BR1CR 0x57 -#define TMP95C063_ODE 0x58 -#define TMP95C063_DMA0V 0x5a -#define TMP95C063_DMA1V 0x5b -#define TMP95C063_DMA2V 0x5c -#define TMP95C063_DMA3V 0x5d -#define TMP95C063_ADMOD1 0x5e -#define TMP95C063_ADMOD2 0x5f -#define TMP95C063_ADREG04L 0x60 -#define TMP95C063_ADREG04H 0x61 -#define TMP95C063_ADREG15L 0x62 -#define TMP95C063_ADREG15H 0x63 -#define TMP95C063_ADREG26L 0x64 -#define TMP95C063_ADREG26H 0x65 -#define TMP95C063_ADREG37L 0x66 -#define TMP95C063_ADREG37H 0x67 -#define TMP95C063_SDMACR0 0x6a -#define TMP95C063_SDMACR1 0x6b -#define TMP95C063_SDMACR2 0x6c -#define TMP95C063_SDMACR3 0x6d -#define TMP95C063_WDMOD 0x6e -#define TMP95C063_WDCR 0x6f -#define TMP95C063_INTE0AD 0x70 -#define TMP95C063_INTE12 0x71 -#define TMP95C063_INTE34 0x72 -#define TMP95C063_INTE56 0x73 -#define TMP95C063_INTE78 0x74 -#define TMP95C063_INTET01 0x75 -#define TMP95C063_INTET23 0x76 -#define TMP95C063_INTET45 0x77 -#define TMP95C063_INTET67 0x78 -#define TMP95C063_INTET89 0x79 -#define TMP95C063_INTETAB 0x7a -#define TMP95C063_INTES0 0x7b -#define TMP95C063_INTES1 0x7c -#define TMP95C063_INTETC01 0x7d -#define TMP95C063_INTETC23 0x7e -#define TMP95C063_IIMC 0x7f -#define TMP95C063_PACR 0x80 -#define TMP95C063_PAFC 0x81 -#define TMP95C063_PBCR 0x82 -#define TMP95C063_PBFC 0x83 -#define TMP95C063_PC 0x84 -#define TMP95C063_PD 0x85 -#define TMP95C063_PDCR 0x88 -#define TMP95C063_PE 0x8a -#define TMP95C063_PECR 0x8c -#define TMP95C063_BEXCS 0x8f -#define TMP95C063_B0CS 0x90 -#define TMP95C063_B1CS 0x91 -#define TMP95C063_B2CS 0x92 -#define TMP95C063_B3CS 0x93 -#define TMP95C063_MSAR0 0x94 -#define TMP95C063_MAMR0 0x95 -#define TMP95C063_MSAR1 0x96 -#define TMP95C063_MAMR1 0x97 -#define TMP95C063_MSAR2 0x98 -#define TMP95C063_MAMR2 0x99 -#define TMP95C063_MSAR3 0x9a -#define TMP95C063_MAMR3 0x9b -#define TMP95C063_DREFCR1 0x9c -#define TMP95C063_DMEMCR1 0x9d -#define TMP95C063_DREFCR3 0x9e -#define TMP95C063_DMEMCR3 0x9f - - -#define TMP95C063_NUM_MASKABLE_IRQS 30 -static const struct { - uint8_t reg; - uint8_t iff; - uint8_t vector; -} tmp95c063_irq_vector_map[TMP95C063_NUM_MASKABLE_IRQS] = -{ - { TMP95C063_INTETC23, 0x80, 0xa0 }, /* INTTC3 */ - { TMP95C063_INTETC23, 0x08, 0x9c }, /* INTTC2 */ - { TMP95C063_INTETC01, 0x80, 0x98 }, /* INTTC1 */ - { TMP95C063_INTETC01, 0x08, 0x94 }, /* INTTC0 */ - { TMP95C063_INTE0AD, 0x80, 0x90 }, /* INTAD */ - { TMP95C063_INTES1, 0x80, 0x8c }, /* INTTX1 */ - { TMP95C063_INTES1, 0x08, 0x88 }, /* INTRX1 */ - { TMP95C063_INTES0, 0x80, 0x84 }, /* INTTX0 */ - { TMP95C063_INTES0, 0x08, 0x80 }, /* INTRX0 */ - { TMP95C063_INTETAB, 0x80, 0x7c }, /* INTTRB */ - { TMP95C063_INTETAB, 0x08, 0x78 }, /* INTTRA */ - { TMP95C063_INTET89, 0x80, 0x74 }, /* INTTR9 */ - { TMP95C063_INTET89, 0x80, 0x70 }, /* INTTR8 */ - { TMP95C063_INTET67, 0x80, 0x6c }, /* INTT7 */ - { TMP95C063_INTET67, 0x08, 0x68 }, /* INTT6 */ - { TMP95C063_INTET45, 0x80, 0x64 }, /* INTT5 */ - { TMP95C063_INTET45, 0x08, 0x60 }, /* INTT4 */ - { TMP95C063_INTET23, 0x80, 0x5c }, /* INTT3 */ - { TMP95C063_INTET23, 0x08, 0x58 }, /* INTT2 */ - { TMP95C063_INTET01, 0x80, 0x54 }, /* INTT1 */ - { TMP95C063_INTET01, 0x08, 0x50 }, /* INTT0 */ - { TMP95C063_INTE78, 0x80, 0x4c }, /* int8_t */ - { TMP95C063_INTE78, 0x08, 0x48 }, /* INT7 */ - { TMP95C063_INTE56, 0x80, 0x44 }, /* INT6 */ - { TMP95C063_INTE56, 0x08, 0x40 }, /* INT5 */ - /* 0x3c - reserved */ - { TMP95C063_INTE34, 0x80, 0x38 }, /* INT4 */ - { TMP95C063_INTE34, 0x08, 0x34 }, /* INT3 */ - { TMP95C063_INTE12, 0x80, 0x30 }, /* INT2 */ - { TMP95C063_INTE12, 0x08, 0x2c }, /* INT1 */ - { TMP95C063_INTE0AD, 0x08, 0x28 } /* INT0 */ -}; - -void tmp95c063_device::tlcs900_handle_timers() -{ - // TODO: implement timers 4-7 - - uint32_t old_pre = m_timer_pre; - - /* Is the pre-scaler active */ - if ( m_reg[TMP95C063_T8RUN] & 0x80 ) - m_timer_pre += m_cycles; - - /* Timer 0 */ - if ( m_reg[TMP95C063_T8RUN] & 0x01 ) - { - switch( m_reg[TMP95C063_T01MOD] & 0x03 ) - { - case 0x00: /* TIO */ - break; - case 0x01: /* T1 */ - m_timer_change[0] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T4 */ - m_timer_change[0] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); - break; - case 0x03: /* T16 */ - m_timer_change[0] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - } - - for( ; m_timer_change[0] > 0; m_timer_change[0]-- ) - { -//printf("timer0 = %02x, TREG0 = %02x\n", m_timer[0], m_reg[TREG0] ); - m_timer[0] += 1; - if ( m_timer[0] == m_reg[TMP95C063_TREG0] ) - { - if ( ( m_reg[TMP95C063_T01MOD] & 0x0c ) == 0x00 ) - { - m_timer_change[1] += 1; - } - - /* In 16bit timer mode the timer should not be reset */ - if ( ( m_reg[TMP95C063_T01MOD] & 0xc0 ) != 0x40 ) - { - m_timer[0] = 0; - m_reg[TMP95C063_INTET01] |= 0x08; - } - } - } - } - - /* Timer 1 */ - if ( m_reg[TMP95C063_T8RUN] & 0x02 ) - { - switch( ( m_reg[TMP95C063_T01MOD] >> 2 ) & 0x03 ) - { - case 0x00: /* TO0TRG */ - break; - case 0x01: /* T1 */ - m_timer_change[1] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T16 */ - m_timer_change[1] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - case 0x03: /* T256 */ - m_timer_change[1] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); - break; - } - - for( ; m_timer_change[1] > 0; m_timer_change[1]-- ) - { - m_timer[1] += 1; - if ( m_timer[1] == m_reg[TMP95C063_TREG1] ) - { - m_timer[1] = 0; - m_reg[TMP95C063_INTET01] |= 0x80; - - if ( m_reg[TMP95C063_T02FFCR] & 0x02 ) - { - //tlcs900_change_tff( 1, FF_INVERT ); - } - - /* In 16bit timer mode also reset timer 0 */ - if ( ( m_reg[TMP95C063_T01MOD] & 0xc0 ) == 0x40 ) - { - m_timer[0] = 0; - } - } - } - } - - /* Timer 2 */ - if ( m_reg[TMP95C063_T8RUN] & 0x04 ) - { - switch( m_reg[TMP95C063_T23MOD] & 0x03 ) - { - case 0x00: /* invalid */ - case 0x01: /* T1 */ - m_timer_change[2] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T4 */ - m_timer_change[2] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); - break; - case 0x03: /* T16 */ - m_timer_change[2] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - } - - for( ; m_timer_change[2] > 0; m_timer_change[2]-- ) - { - m_timer[2] += 1; - if ( m_timer[2] == m_reg[TMP95C063_TREG2] ) - { - if ( ( m_reg[TMP95C063_T23MOD] & 0x0c ) == 0x00 ) - { - m_timer_change[3] += 1; - } - - /* In 16bit timer mode the timer should not be reset */ - if ( ( m_reg[TMP95C063_T23MOD] & 0xc0 ) != 0x40 ) - { - m_timer[2] = 0; - m_reg[TMP95C063_INTET23] |= 0x08; - } - } - } - } - - /* Timer 3 */ - if ( m_reg[TMP95C063_T8RUN] & 0x08 ) - { - switch( ( m_reg[TMP95C063_T23MOD] >> 2 ) & 0x03 ) - { - case 0x00: /* TO2TRG */ - break; - case 0x01: /* T1 */ - m_timer_change[3] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); - break; - case 0x02: /* T16 */ - m_timer_change[3] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); - break; - case 0x03: /* T256 */ - m_timer_change[3] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); - break; - } - - for( ; m_timer_change[3] > 0; m_timer_change[3]-- ) - { - m_timer[3] += 1; - if ( m_timer[3] == m_reg[TMP95C061_TREG3] ) - { - m_timer[3] = 0; - m_reg[TMP95C063_INTET23] |= 0x80; - - if ( m_reg[TMP95C063_T02FFCR] & 0x20 ) - { - //tlcs900_change_tff( 3, FF_INVERT ); - } - - /* In 16bit timer mode also reset timer 2 */ - if ( ( m_reg[TMP95C063_T23MOD] & 0xc0 ) == 0x40 ) - { - m_timer[2] = 0; - } - } - } - } - - m_timer_pre &= 0xffffff; -} - -void tmp95c063_device::tlcs900_check_hdma() -{ - // TODO -} - -void tmp95c063_device::tlcs900_check_irqs() -{ - int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - int level = 0; - int irq = -1; - int i; - - /* Check for NMI */ - if ( m_nmi_state == ASSERT_LINE ) - { - m_xssp.d -= 4; - WRMEML( m_xssp.d, m_pc.d ); - m_xssp.d -= 2; - WRMEMW( m_xssp.d, m_sr.w.l ); - m_pc.d = RDMEML( 0xffff00 + 0x20 ); - m_cycles += 18; - m_prefetch_clear = true; - - m_halted = 0; - - m_nmi_state = CLEAR_LINE; - - return; - } - - /* Check regular irqs */ - for( i = 0; i < TMP95C063_NUM_MASKABLE_IRQS; i++ ) - { - if ( m_reg[tmp95c063_irq_vector_map[i].reg] & tmp95c063_irq_vector_map[i].iff ) - { - switch( tmp95c063_irq_vector_map[i].iff ) - { - case 0x80: - irq_vectors[ ( m_reg[ tmp95c063_irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i; - break; - case 0x08: - irq_vectors[ m_reg[ tmp95c063_irq_vector_map[i].reg ] & 0x07 ] = i; - break; - } - } - } - - /* Check highest allowed priority irq */ - for ( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) - { - if ( irq_vectors[i] >= 0 ) - { - irq = irq_vectors[i]; - level = i + 1; - } - } - - /* Take irq */ - if ( irq >= 0 ) - { - uint8_t vector = tmp95c063_irq_vector_map[irq].vector; - - m_xssp.d -= 4; - WRMEML( m_xssp.d, m_pc.d ); - m_xssp.d -= 2; - WRMEMW( m_xssp.d, m_sr.w.l ); - - /* Mask off any lower priority interrupts */ - m_sr.b.h = ( m_sr.b.h & 0x8f ) | ( level << 4 ); - - m_pc.d = RDMEML( 0xffff00 + vector ); - m_cycles += 18; - m_prefetch_clear = true; - - m_halted = 0; - - /* Clear taken IRQ */ - m_reg[ tmp95c063_irq_vector_map[irq].reg ] &= ~ tmp95c063_irq_vector_map[irq].iff; - } -} - - -void tmp95c063_device::tlcs900_handle_ad() -{ - if ( m_ad_cycles_left > 0 ) - { - m_ad_cycles_left -= m_cycles; - if ( m_ad_cycles_left <= 0 ) - { - int ad_value; - - /* Store A/D converted value */ - if ((m_reg[TMP95C063_ADMOD1] & 0x10) == 0) // conversion channel fixed - { - switch( m_reg[TMP95C063_ADMOD2] & 0x07 ) - { - case 0x00: // AN0 - ad_value = m_an_read[0](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - break; - case 0x01: // AN1 - ad_value = m_an_read[1](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - break; - case 0x02: // AN2 - ad_value = m_an_read[2](0) & 0x3ff; - m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; - break; - case 0x03: // AN3 - ad_value = m_an_read[3](0) & 0x3ff; - m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; - break; - case 0x04: // AN4 - ad_value = m_an_read[4](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - break; - case 0x05: // AN5 - ad_value = m_an_read[5](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - break; - case 0x06: // AN6 - ad_value = m_an_read[6](0) & 0x3ff; - m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; - break; - case 0x07: // AN7 - ad_value = m_an_read[7](0) & 0x3ff; - m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; - break; - } - } - else // conversion channel sweep - { - switch( m_reg[TMP95C063_ADMOD2] & 0x07 ) - { - case 0x00: // AN0 - ad_value = m_an_read[0](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - break; - case 0x01: // AN0 -> AN1 - ad_value = m_an_read[0](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[1](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - break; - case 0x02: // AN0 -> AN1 -> AN2 - ad_value = m_an_read[0](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[1](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[2](0) & 0x3ff; - m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; - break; - case 0x03: // AN0 -> AN1 -> AN2 -> AN3 - ad_value = m_an_read[0](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[1](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[2](0) & 0x3ff; - m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[3](0) & 0x3ff; - m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; - break; - case 0x04: // AN4 - ad_value = m_an_read[4](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - break; - case 0x05: // AN4 -> AN5 - ad_value = m_an_read[4](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[5](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - break; - case 0x06: // AN4 -> AN5 -> AN6 - ad_value = m_an_read[4](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[5](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[6](0) & 0x3ff; - m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; - break; - case 0x07: // AN4 -> AN5 -> AN6 -> AN7 - ad_value = m_an_read[4](0) & 0x3ff; - m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[5](0) & 0x3ff; - m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[6](0) & 0x3ff; - m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; - ad_value = m_an_read[7](0) & 0x3ff; - m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; - m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; - break; - } - } - - /* Clear BUSY flag, set END flag */ - m_reg[TMP95C063_ADMOD1] &= ~ 0x40; - m_reg[TMP95C063_ADMOD1] |= 0x80; - - m_reg[TMP95C063_INTE0AD] |= 0x80; - m_check_irqs = 1; - } - } -} - - -void tmp95c063_device::device_start() -{ - tlcs900h_device::device_start(); - - m_port1_read.resolve_safe(0); - m_port1_write.resolve_safe(); - m_port2_write.resolve_safe(); - m_port5_read.resolve_safe(0); - m_port5_write.resolve_safe(); - m_port6_read.resolve_safe(0); - m_port6_write.resolve_safe(); - m_port7_read.resolve_safe(0); - m_port7_write.resolve_safe(); - m_port8_read.resolve_safe(0); - m_port8_write.resolve_safe(); - m_port9_read.resolve_safe(0); - m_port9_write.resolve_safe(); - m_porta_read.resolve_safe(0); - m_porta_write.resolve_safe(); - m_portb_read.resolve_safe(0); - m_portb_write.resolve_safe(); - m_portc_read.resolve_safe(0); - m_portd_read.resolve_safe(0); - m_portd_write.resolve_safe(); - m_porte_read.resolve_safe(0); - m_porte_write.resolve_safe(); - m_an_read.resolve_all_safe(0); -} - -void tmp95c063_device::device_reset() -{ - m_pc.b.l = RDMEM( 0xFFFF00 ); - m_pc.b.h = RDMEM( 0xFFFF01 ); - m_pc.b.h2 = RDMEM( 0xFFFF02 ); - m_pc.b.h3 = 0; - /* system mode, iff set to 111, max mode, register bank 0 */ - m_sr.d = 0xF800; - m_regbank = 0; - m_xssp.d = 0x0100; - m_halted = 0; - m_check_irqs = 0; - m_ad_cycles_left = 0; - m_nmi_state = CLEAR_LINE; - m_timer_pre = 0; - m_timer_change[0] = 0; - m_timer_change[1] = 0; - m_timer_change[2] = 0; - m_timer_change[3] = 0; - - m_reg[TMP95C063_P1] = 0x00; - m_reg[TMP95C063_P1CR] = 0x00; - m_reg[TMP95C063_P2] = 0xff; - m_reg[TMP95C063_P2FC] = 0x00; - m_reg[TMP95C063_P5] = 0x3d; - m_reg[TMP95C063_P5CR] = 0x00; - m_reg[TMP95C063_P5FC] = 0x00; - m_reg[TMP95C063_P6] = 0x3b; - m_reg[TMP95C063_P6FC] = 0x00; - m_reg[TMP95C063_P7] = 0xff; - m_reg[TMP95C063_P7CR] = 0x00; - m_reg[TMP95C063_P7FC] = 0x00; - m_reg[TMP95C063_P8] = 0x3f; - m_reg[TMP95C063_P8CR] = 0x00; - m_reg[TMP95C063_P8FC] = 0x00; - m_reg[TMP95C063_PA] = 0x0f; - m_reg[TMP95C063_PACR] = 0x00; - m_reg[TMP95C063_PAFC] = 0x00; - m_reg[TMP95C063_PB] = 0xff; - m_reg[TMP95C063_PBCR] = 0x00; - m_reg[TMP95C063_PBFC] = 0x00; - m_reg[TMP95C063_MSAR0] = 0xff; - m_reg[TMP95C063_MSAR1] = 0xff; - m_reg[TMP95C063_MSAR2] = 0xff; - m_reg[TMP95C063_MSAR3] = 0xff; - m_reg[TMP95C063_MAMR0] = 0xff; - m_reg[TMP95C063_MAMR1] = 0xff; - m_reg[TMP95C063_MAMR2] = 0xff; - m_reg[TMP95C063_MAMR3] = 0xff; - m_reg[TMP95C063_DREFCR1] = 0x00; - m_reg[TMP95C063_DMEMCR1] = 0x80; - m_reg[TMP95C063_DREFCR3] = 0x00; - m_reg[TMP95C063_DMEMCR3] = 0x80; - m_reg[TMP95C063_T01MOD] = 0x00; - m_reg[TMP95C063_T23MOD] = 0x00; - m_reg[TMP95C063_T02FFCR] = 0x00; - m_reg[TMP95C063_T46FFCR] = 0x00; - m_reg[TMP95C063_T8RUN] = 0x00; - m_reg[TMP95C063_TRDC] = 0x00; - m_reg[TMP95C063_T45MOD] = 0x20; - m_reg[TMP95C063_T46FFCR] = 0x00; - m_reg[TMP95C063_PG01CR] = 0x00; - m_reg[TMP95C063_PG0REG] = 0x00; - m_reg[TMP95C063_PG1REG] = 0x00; - m_reg[TMP95C063_SC0MOD] = 0x00; - m_reg[TMP95C063_SC0CR] = 0x00; - m_reg[TMP95C063_BR0CR] = 0x00; - m_reg[TMP95C063_SC1MOD] = 0x00; - m_reg[TMP95C063_SC1CR] = 0x00; - m_reg[TMP95C063_BR1CR] = 0x00; - m_reg[TMP95C063_P8FC] = 0x00; - m_reg[TMP95C063_ODE] = 0x00; - m_reg[TMP95C063_ADMOD1] = 0x00; - m_reg[TMP95C063_ADMOD2] = 0x00; - m_reg[TMP95C063_ADREG04L] = 0x3f; - m_reg[TMP95C063_ADREG04H] = 0x00; - m_reg[TMP95C063_ADREG15L] = 0x3f; - m_reg[TMP95C063_ADREG15H] = 0x00; - m_reg[TMP95C063_ADREG26L] = 0x3f; - m_reg[TMP95C063_ADREG26H] = 0x00; - m_reg[TMP95C063_ADREG37L] = 0x3f; - m_reg[TMP95C063_ADREG37H] = 0x00; - m_reg[TMP95C063_WDMOD] = 0x80; - - for (int i = 0; i < TLCS900_NUM_INPUTS; i++) - m_level[i] = CLEAR_LINE; - - m_prefetch_clear = true; -} - -uint8_t tmp95c063_device::internal_r(offs_t offset) -{ - switch (offset) - { - case TMP95C063_P1: m_reg[offset] = m_port1_read(0); break; - case TMP95C063_P5: m_reg[offset] = m_port5_read(0); break; - case TMP95C063_P6: m_reg[offset] = m_port6_read(0); break; - case TMP95C063_P7: m_reg[offset] = m_port7_read(0); break; - case TMP95C063_P8: m_reg[offset] = m_port8_read(0); break; - case TMP95C063_P9: m_reg[offset] = m_port9_read(0); break; - case TMP95C063_PA: m_reg[offset] = m_porta_read(0); break; - case TMP95C063_PB: m_reg[offset] = m_portb_read(0); break; - case TMP95C063_PC: m_reg[offset] = m_portc_read(0); break; - case TMP95C063_PD: m_reg[offset] = m_portd_read(0); break; - case TMP95C063_PE: m_reg[offset] = m_porte_read(0); break; - } - return m_reg[ offset ]; -} - - -void tmp95c063_device::internal_w(offs_t offset, uint8_t data) -{ - switch ( offset ) - { - case TMP95C063_T8RUN: - if ( ! ( data & 0x01 ) ) - { - m_timer[0] = 0; - m_timer_change[0] = 0; - } - if ( ! ( data & 0x02 ) ) - { - m_timer[1] = 0; - m_timer_change[1] = 0; - } - if ( ! ( data & 0x04 ) ) - { - m_timer[2] = 0; - m_timer_change[2] = 0; - } - if ( ! ( data & 0x08 ) ) - { - m_timer[3] = 0; - m_timer_change[3] = 0; - } - if ( ! ( data & 0x10 ) ) - m_timer[4] = 0; - if ( ! ( data & 0x20 ) ) - m_timer[5] = 0; - break; - - case TMP95C063_T02FFCR: - switch( data & 0x0c ) - { - case 0x00: - //tlcs900_change_tff( 1, FF_INVERT ); - break; - case 0x04: - //tlcs900_change_tff( 1, FF_SET ); - break; - case 0x08: - //tlcs900_change_tff( 1, FF_CLEAR ); - break; - } - switch( data & 0xc0 ) - { - case 0x00: - //tlcs900_change_tff( 3, FF_INVERT ); - break; - case 0x40: - //tlcs900_change_tff( 3, FF_SET ); - break; - case 0x80: - //tlcs900_change_tff( 3, FF_CLEAR ); - break; - } - break; - - case TMP95C063_T46FFCR: - switch( data & 0x0c ) - { - case 0x00: - //tlcs900_change_tff( 5, FF_INVERT ); - break; - case 0x04: - //tlcs900_change_tff( 5, FF_SET ); - break; - case 0x08: - //tlcs900_change_tff( 5, FF_CLEAR ); - break; - } - switch( data & 0xc0 ) - { - case 0x00: - //tlcs900_change_tff( 7, FF_INVERT ); - break; - case 0x40: - //tlcs900_change_tff( 7, FF_SET ); - break; - case 0x80: - //tlcs900_change_tff( 7, FF_CLEAR ); - break; - } - break; - - case TMP95C063_T8FFCR: - switch( data & 0x03 ) - { - case 0x00: - //tlcs900_change_tff( 8, FF_INVERT ); - break; - case 0x01: - //tlcs900_change_tff( 8, FF_SET ); - break; - case 0x02: - //tlcs900_change_tff( 8, FF_CLEAR ); - break; - } - switch( data & 0xc0 ) - { - case 0x00: - //tlcs900_change_tff( 9, FF_INVERT ); - break; - case 0x40: - //tlcs900_change_tff( 9, FF_SET ); - break; - case 0x80: - //tlcs900_change_tff( 9, FF_CLEAR ); - break; - } - break; - - case TMP95C063_T9FFCR: - switch( data & 0x03 ) - { - case 0x00: - //tlcs900_change_tff( 0xa, FF_INVERT ); - break; - case 0x01: - //tlcs900_change_tff( 0xa, FF_SET ); - break; - case 0x02: - //tlcs900_change_tff( 0xa, FF_CLEAR ); - break; - } - switch( data & 0xc0 ) - { - case 0x00: - //tlcs900_change_tff( 0xb, FF_INVERT ); - break; - case 0x40: - //tlcs900_change_tff( 0xb, FF_SET ); - break; - case 0x80: - //tlcs900_change_tff( 0xb, FF_CLEAR ); - break; - } - break; - - case TMP95C063_MSAR0: - case TMP95C063_MAMR0: - case TMP95C063_MSAR1: - case TMP95C063_MAMR1: - break; - - case TMP95C063_WDMOD: - case TMP95C063_WDCR: - break; - - case TMP95C063_INTE0AD: - case TMP95C063_INTE12: - case TMP95C063_INTE34: - case TMP95C063_INTE56: - case TMP95C063_INTE78: - case TMP95C063_INTET01: - case TMP95C063_INTET23: - case TMP95C063_INTET45: - case TMP95C063_INTET67: - case TMP95C063_INTET89: - case TMP95C063_INTETAB: - case TMP95C063_INTES0: - case TMP95C063_INTES1: - case TMP95C063_INTETC01: - case TMP95C063_INTETC23: - if ( data & 0x80 ) - data = ( data & 0x7f ) | ( m_reg[offset] & 0x80 ); - if ( data & 0x08 ) - data = ( data & 0xf7 ) | ( m_reg[offset] & 0x08 ); - break; - - case TMP95C063_IIMC: - break; - - case TMP95C063_ADMOD1: - // conversion start - if (data & 0x04) - { - data &= ~0x04; - data |= 0x40; - - switch ((m_reg[TMP95C063_ADMOD2] >> 4) & 3) - { - case 0: m_ad_cycles_left = 160; break; - case 1: m_ad_cycles_left = 320; break; - case 2: m_ad_cycles_left = 640; break; - case 3: m_ad_cycles_left = 1280; break; - } - } - break; - - case TMP95C063_ADMOD2: - break; - - default: - break; - } - - m_check_irqs = 1; - m_reg[ offset ] = data; - - switch (offset) - { - case TMP95C063_P1: m_port1_write(0, data, 0xff); break; - case TMP95C063_P2: m_port2_write(0, data, 0xff); break; - case TMP95C063_P5: m_port5_write(0, data, 0xff); break; - case TMP95C063_P6: m_port6_write(0, data, 0xff); break; - case TMP95C063_P7: m_port7_write(0, data, 0xff); break; - case TMP95C063_P8: m_port8_write(0, data, 0xff); break; - case TMP95C063_P9: m_port9_write(0, data, 0xff); break; - case TMP95C063_PA: m_porta_write(0, data, 0xff); break; - case TMP95C063_PB: m_portb_write(0, data, 0xff); break; - //case TMP95C063_PC: m_portc_write(0, data, 0xff); break; - case TMP95C063_PD: m_portd_write(0, data, 0xff); break; - case TMP95C063_PE: m_porte_write(0, data, 0xff); break; - } -} - - -void tmp95c063_device::execute_set_input(int input, int level) -{ - switch( input ) - { - case INPUT_LINE_NMI: - case TLCS900_NMI: - if ( m_level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_nmi_state = level; - } - m_level[TLCS900_NMI] = level; - break; - - case TLCS900_INTWD: - break; - - case TLCS900_INT0: - /* Is INT0 functionality enabled? */ - if (m_reg[TMP95C063_IIMC] & 0x04) - { - if (m_reg[TMP95C063_IIMC] & 0x02) - { - /* Rising edge detect */ - if (m_level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE) - { - /* Leave HALT state */ - m_halted = 0; - m_reg[TMP95C063_INTE0AD] |= 0x08; - } - } - else - { - /* Level detect */ - if (level == ASSERT_LINE) - m_reg[TMP95C063_INTE0AD] |= 0x08; - else - m_reg[TMP95C063_INTE0AD] &= ~ 0x08; - } - } - m_level[TLCS900_INT0] = level; - break; - - case TLCS900_INT1: - if (m_level[TLCS900_INT1] == CLEAR_LINE && level == ASSERT_LINE) - { - m_reg[TMP95C063_INTE12] |= 0x08; - } - else if (m_level[TLCS900_INT1] == ASSERT_LINE && level == CLEAR_LINE) - { - m_reg[TMP95C063_INTE12] &= ~0x08; - } - m_level[TLCS900_INT1] = level; - break; - - case TLCS900_INT2: - if (m_level[TLCS900_INT2] == CLEAR_LINE && level == ASSERT_LINE) - { - m_reg[TMP95C063_INTE12] |= 0x80; - } - else if (m_level[TLCS900_INT2] == ASSERT_LINE && level == CLEAR_LINE) - { - m_reg[TMP95C063_INTE12] &= ~0x80; - } - m_level[TLCS900_INT2] = level; - break; - - case TLCS900_INT3: - if (m_level[TLCS900_INT3] == CLEAR_LINE && level == ASSERT_LINE) - { - m_reg[TMP95C063_INTE34] |= 0x08; - } - else if (m_level[TLCS900_INT3] == ASSERT_LINE && level == CLEAR_LINE) - { - m_reg[TMP95C063_INTE34] &= ~0x08; - } - m_level[TLCS900_INT3] = level; - break; - - case TLCS900_INT4: - if ( ! ( m_reg[TMP95C063_PBCR] & 0x01 ) ) - { - if ( m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_reg[TMP95C063_INTE34] |= 0x80; - } - } - m_level[TLCS900_INT4] = level; - break; - - case TLCS900_INT5: - if ( ! ( m_reg[TMP95C063_PBCR] & 0x02 ) ) - { - if ( m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_reg[TMP95C063_INTE56] |= 0x08; - } - } - m_level[TLCS900_INT5] = level; - break; - - case TLCS900_INT6: - if (m_level[TLCS900_INT6] == CLEAR_LINE && level == ASSERT_LINE) - { - m_reg[TMP95C063_INTE56] |= 0x80; - } - else if (m_level[TLCS900_INT6] == ASSERT_LINE && level == CLEAR_LINE) - { - m_reg[TMP95C063_INTE56] &= ~0x80; - } - m_level[TLCS900_INT6] = level; - break; - - case TLCS900_TIO: /* External timer input for timer 0 */ - if ( ( m_reg[TMP95C063_T8RUN] & 0x01 ) && ( m_reg[TMP95C063_T01MOD] & 0x03 ) == 0x00 ) - { - if ( m_level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE ) - { - m_timer_change[0] += 1; - } - } - m_level[TLCS900_TIO] = level; - break; - } - m_check_irqs = 1; -} diff --git a/src/devices/cpu/tlcs900/tlcs900.h b/src/devices/cpu/tlcs900/tlcs900.h index e886ba868e4..1007479c787 100644 --- a/src/devices/cpu/tlcs900/tlcs900.h +++ b/src/devices/cpu/tlcs900/tlcs900.h @@ -40,10 +40,6 @@ enum }; -DECLARE_DEVICE_TYPE(TMP95C061, tmp95c061_device) -DECLARE_DEVICE_TYPE(TMP95C063, tmp95c063_device) - - class tlcs900h_device : public cpu_device { public: @@ -610,185 +606,4 @@ protected: void op_F0(); }; -class tmp95c061_device : public tlcs900h_device -{ -public: - // construction/destruction - tmp95c061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - // configuration helpers - auto port1_read() { return m_port1_read.bind(); } - auto port1_write() { return m_port1_write.bind(); } - auto port2_write() { return m_port2_write.bind(); } - auto port5_read() { return m_port5_read.bind(); } - auto port5_write() { return m_port5_write.bind(); } - auto port6_write() { return m_port6_write.bind(); } - auto port7_read() { return m_port7_read.bind(); } - auto port7_write() { return m_port7_write.bind(); } - auto port8_read() { return m_port8_read.bind(); } - auto port8_write() { return m_port8_write.bind(); } - auto port9_read() { return m_port9_read.bind(); } - auto porta_read() { return m_porta_read.bind(); } - auto porta_write() { return m_porta_write.bind(); } - auto portb_read() { return m_portb_read.bind(); } - auto portb_write() { return m_portb_write.bind(); } - - uint8_t internal_r(offs_t offset); - void internal_w(offs_t offset, uint8_t data); - - void tmp95c061_mem16(address_map &map); - void tmp95c061_mem8(address_map &map); -protected: - virtual void device_config_complete() override; - virtual void device_start() override; - virtual void device_reset() override; - - virtual void execute_set_input(int inputnum, int state) override; - virtual void tlcs900_check_hdma() override; - virtual void tlcs900_check_irqs() override; - virtual void tlcs900_handle_ad() override; - virtual void tlcs900_handle_timers() override; - - void tlcs900_change_tff( int which, int change ); - int tlcs900_process_hdma( int channel ); - void update_porta(); - -private: - uint8_t m_to1; - uint8_t m_to3; - - // Port 1: 8 bit I/O. Shared with D8-D15 - devcb_read8 m_port1_read; - devcb_write8 m_port1_write; - - // Port 2: 8 bit output only. Shared with A16-A23 - devcb_write8 m_port2_write; - - // Port 5: 4 bit I/O. Shared with HWR, BUSRQ, BUSAK, RW - devcb_read8 m_port5_read; - devcb_write8 m_port5_write; - - // Port 6: 6 bit I/O. Shared with CS0, CS1, CS3/LCAS, RAS, REFOUT - devcb_read8 m_port6_read; - devcb_write8 m_port6_write; - - // Port 7: 8 bit I/O. Shared with PG0-OUT, PG1-OUT - devcb_read8 m_port7_read; - devcb_write8 m_port7_write; - - // Port 8: 6 bit I/O. Shared with TXD0, TXD1, RXD0, RXD1, CTS0, SCLK0, SCLK1 - devcb_read8 m_port8_read; - devcb_write8 m_port8_write; - - // Port 9: 4 bit input only. Shared with AN0-AN3 - devcb_read8 m_port9_read; - - // Port A: 4 bit I/O. Shared with WAIT, TI0, TO1, TO2 - devcb_read8 m_porta_read; - devcb_write8 m_porta_write; - - // Port B: 8 bit I/O. Shared with TI4/INT4, TI5/INT5, TI6/INT6, TI7/INT7, TO4, TO5, TO6 - devcb_read8 m_portb_read; - devcb_write8 m_portb_write; -}; - - -class tmp95c063_device : public tlcs900h_device -{ -public: - // construction/destruction - tmp95c063_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - uint8_t internal_r(offs_t offset); - void internal_w(offs_t offset, uint8_t data); - - // configuration helpers - auto port1_read() { return m_port1_read.bind(); } - auto port1_write() { return m_port1_write.bind(); } - auto port2_write() { return m_port2_write.bind(); } - auto port5_read() { return m_port5_read.bind(); } - auto port5_write() { return m_port5_write.bind(); } - auto port6_read() { return m_port6_read.bind(); } - auto port6_write() { return m_port6_write.bind(); } - auto port7_read() { return m_port7_read.bind(); } - auto port7_write() { return m_port7_write.bind(); } - auto port8_read() { return m_port8_read.bind(); } - auto port8_write() { return m_port8_write.bind(); } - auto port9_read() { return m_port9_read.bind(); } - auto port9_write() { return m_port9_write.bind(); } - auto porta_read() { return m_porta_read.bind(); } - auto porta_write() { return m_porta_write.bind(); } - auto portb_read() { return m_portb_read.bind(); } - auto portb_write() { return m_portb_write.bind(); } - auto portc_read() { return m_portc_read.bind(); } - auto portd_read() { return m_portd_read.bind(); } - auto portd_write() { return m_portd_write.bind(); } - auto porte_read() { return m_porte_read.bind(); } - auto porte_write() { return m_porte_write.bind(); } - template auto an_read() { return m_an_read[Bit].bind(); } - - void tmp95c063_mem16(address_map &map); - void tmp95c063_mem8(address_map &map); -protected: - virtual void device_config_complete() override; - virtual void device_start() override; - virtual void device_reset() override; - - virtual void execute_set_input(int inputnum, int state) override; - virtual void tlcs900_check_hdma() override; - virtual void tlcs900_check_irqs() override; - virtual void tlcs900_handle_ad() override; - virtual void tlcs900_handle_timers() override; - -private: - // Port 1: 8 bit I/O. Shared with d8-d15 - devcb_read8 m_port1_read; - devcb_write8 m_port1_write; - - // Port 2: 8 bit output only. Shared with a16-a23 - devcb_write8 m_port2_write; - - // Port 5: 6 bit I/O - devcb_read8 m_port5_read; - devcb_write8 m_port5_write; - - // Port 6: 8 bit I/O. Shared with cs1, cs3 & dram control - devcb_read8 m_port6_read; - devcb_write8 m_port6_write; - - // Port 7: 8 bit I/O - devcb_read8 m_port7_read; - devcb_write8 m_port7_write; - - // Port 8: 8 bit I/O. Shared with SCOUT, WAIT, NMI2, INT0-INT3 - devcb_read8 m_port8_read; - devcb_write8 m_port8_write; - - // Port 9: 8 bit I/O. Shared with clock input and output for the 8-bit timers - devcb_read8 m_port9_read; - devcb_write8 m_port9_write; - - // Port A: 8 bit I/O. Shared with serial channels 0/1 - devcb_read8 m_porta_read; - devcb_write8 m_porta_write; - - // Port B: 8 bit I/O. Shared with 16bit timers - devcb_read8 m_portb_read; - devcb_write8 m_portb_write; - - // Port C: 8 bit input only. Shared with analogue inputs - devcb_read8 m_portc_read; - - // Port D: 5 bit I/O. Shared with int8_t - devcb_read8 m_portd_read; - devcb_write8 m_portd_write; - - // Port E: 8 bit I/O. - devcb_read8 m_porte_read; - devcb_write8 m_porte_write; - - // analogue inputs, sampled at 10 bits - devcb_read16::array<8> m_an_read; -}; - #endif // MAME_CPU_TLCS900_TLCS900_H diff --git a/src/devices/cpu/tlcs900/tmp95c061.cpp b/src/devices/cpu/tlcs900/tmp95c061.cpp new file mode 100644 index 00000000000..9116078d036 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp95c061.cpp @@ -0,0 +1,1022 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/******************************************************************* + +Toshiba TMP95C061 emulation + +*******************************************************************/ + +#include "emu.h" +#include "tmp95c061.h" + +DEFINE_DEVICE_TYPE(TMP95C061, tmp95c061_device, "tmp95c061", "Toshiba TMP95C061") + + +tmp95c061_device::tmp95c061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + tlcs900h_device(mconfig, TMP95C061, tag, owner, clock), + m_port1_read(*this), + m_port1_write(*this), + m_port2_write(*this), + m_port5_read(*this), + m_port5_write(*this), + m_port6_read(*this), + m_port6_write(*this), + m_port7_read(*this), + m_port7_write(*this), + m_port8_read(*this), + m_port8_write(*this), + m_port9_read(*this), + m_porta_read(*this), + m_porta_write(*this), + m_portb_read(*this), + m_portb_write(*this) +{ +} + +void tmp95c061_device::internal_mem(address_map &map) +{ + map(0x000000, 0x00007f).rw(FUNC(tmp95c061_device::internal_r), FUNC(tmp95c061_device::internal_w)); +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void tmp95c061_device::device_config_complete() +{ + if (m_am8_16 == 0) + { + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp95c061_device::internal_mem), this)); + } + else + { + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp95c061_device::internal_mem), this)); + } +} + + + +/* Internal register defines */ +#define TMP95C061_P1 0x01 +#define TMP95C061_P1CR 0x02 +#define TMP95C061_P2 0x06 +#define TMP95C061_P2FC 0x09 +#define TMP95C061_P5 0x0d +#define TMP95C061_P5CR 0x10 +#define TMP95C061_P5FC 0x11 +#define TMP95C061_P6 0x12 +#define TMP95C061_P7 0x13 +#define TMP95C061_P6FC 0x15 +#define TMP95C061_P7CR 0x16 +#define TMP95C061_P7FC 0x17 +#define TMP95C061_P8 0x18 +#define TMP95C061_P9 0x19 +#define TMP95C061_P8CR 0x1a +#define TMP95C061_P8FC 0x1b +#define TMP95C061_PA 0x1e +#define TMP95C061_PB 0x1f +#define TMP95C061_TRUN 0x20 +#define TMP95C061_TREG0 0x22 +#define TMP95C061_TREG1 0x23 +#define TMP95C061_T01MOD 0x24 +#define TMP95C061_TFFCR 0x25 +#define TMP95C061_TREG2 0x26 +#define TMP95C061_TREG3 0x27 +#define TMP95C061_T23MOD 0x28 +#define TMP95C061_TRDC 0x29 +#define TMP95C061_PACR 0x2c +#define TMP95C061_PAFC 0x2d +#define TMP95C061_PBCR 0x2e +#define TMP95C061_PBFC 0x2f +#define TMP95C061_TREG4L 0x30 +#define TMP95C061_TREG4H 0x31 +#define TMP95C061_TREG5L 0x32 +#define TMP95C061_TREG5H 0x33 +#define TMP95C061_CAP1L 0x34 +#define TMP95C061_CAP1H 0x35 +#define TMP95C061_CAP2L 0x36 +#define TMP95C061_CAP2H 0x37 +#define TMP95C061_T4MOD 0x38 +#define TMP95C061_T4FFCR 0x39 +#define TMP95C061_T45CR 0x3a +#define TMP95C061_MSAR0 0x3c +#define TMP95C061_MAMR0 0x3d +#define TMP95C061_MSAR1 0x3e +#define TMP95C061_MAMR1 0x3f +#define TMP95C061_TREG6L 0x40 +#define TMP95C061_TREG6H 0x41 +#define TMP95C061_TREG7L 0x42 +#define TMP95C061_TREG7H 0x43 +#define TMP95C061_CAP3L 0x44 +#define TMP95C061_CAP3H 0x45 +#define TMP95C061_CAP4L 0x46 +#define TMP95C061_CAP4H 0x47 +#define TMP95C061_T5MOD 0x48 +#define TMP95C061_T5FFCR 0x49 +#define TMP95C061_PG0REG 0x4c +#define TMP95C061_PG1REG 0x4d +#define TMP95C061_PG01CR 0x4e +#define TMP95C061_SC0BUF 0x50 +#define TMP95C061_SC0CR 0x51 +#define TMP95C061_SC0MOD 0x52 +#define TMP95C061_BR0CR 0x53 +#define TMP95C061_SC1BUF 0x54 +#define TMP95C061_SC1CR 0x55 +#define TMP95C061_SC1MOD 0x56 +#define TMP95C061_BR1CR 0x57 +#define TMP95C061_ODE 0x58 +#define TMP95C061_DREFCR 0x5a +#define TMP95C061_DMEMCR 0x5b +#define TMP95C061_MSAR2 0x5c +#define TMP95C061_MAMR2 0x5d +#define TMP95C061_MSAR3 0x5e +#define TMP95C061_MAMR3 0x5f +#define TMP95C061_ADREG0L 0x60 +#define TMP95C061_ADREG0H 0x61 +#define TMP95C061_ADREG1L 0x62 +#define TMP95C061_ADREG1H 0x63 +#define TMP95C061_ADREG2L 0x64 +#define TMP95C061_ADREG2H 0x65 +#define TMP95C061_ADREG3L 0x66 +#define TMP95C061_ADREG3H 0x67 +#define TMP95C061_B0CS 0x68 +#define TMP95C061_B1CS 0x69 +#define TMP95C061_B2CS 0x6a +#define TMP95C061_B3CS 0x6b +#define TMP95C061_BEXCS 0x6c +#define TMP95C061_ADMOD 0x6d +#define TMP95C061_WDMOD 0x6e +#define TMP95C061_WDCR 0x6f +#define TMP95C061_INTE0AD 0x70 +#define TMP95C061_INTE45 0x71 +#define TMP95C061_INTE67 0x72 +#define TMP95C061_INTET10 0x73 +#define TMP95C061_INTET32 0x74 +#define TMP95C061_INTET54 0x75 +#define TMP95C061_INTET76 0x76 +#define TMP95C061_INTES0 0x77 +#define TMP95C061_INTES1 0x78 +#define TMP95C061_INTETC10 0x79 +#define TMP95C061_INTETC32 0x7a +#define TMP95C061_IIMC 0x7b +#define TMP95C061_DMA0V 0x7c +#define TMP95C061_DMA1V 0x7d +#define TMP95C061_DMA2V 0x7e +#define TMP95C061_DMA3V 0x7f + + +void tmp95c061_device::device_start() +{ + tlcs900h_device::device_start(); + + save_item( NAME(m_to1) ); + save_item( NAME(m_to3) ); + + m_port1_read.resolve_safe(0); + m_port1_write.resolve_safe(); + m_port2_write.resolve_safe(); + m_port5_read.resolve_safe(0); + m_port5_write.resolve_safe(); + m_port6_read.resolve_safe(0); + m_port6_write.resolve_safe(); + m_port7_read.resolve_safe(0); + m_port7_write.resolve_safe(); + m_port8_read.resolve_safe(0); + m_port8_write.resolve_safe(); + m_port9_read.resolve_safe(0); + m_porta_read.resolve_safe(0); + m_porta_write.resolve_safe(); + m_portb_read.resolve_safe(0); + m_portb_write.resolve_safe(); +} + +void tmp95c061_device::device_reset() +{ + int i; + + m_to1 = 0; + m_to3 = 0; + + m_pc.b.l = RDMEM( 0xFFFF00 ); + m_pc.b.h = RDMEM( 0xFFFF01 ); + m_pc.b.h2 = RDMEM( 0xFFFF02 ); + m_pc.b.h3 = 0; + /* system mode, iff set to 111, max mode, register bank 0 */ + m_sr.d = 0xF800; + m_regbank = 0; + m_xssp.d = 0x0100; + m_halted = 0; + m_check_irqs = 0; + m_ad_cycles_left = 0; + m_nmi_state = CLEAR_LINE; + m_timer_pre = 0; + m_timer_change[0] = 0; + m_timer_change[1] = 0; + m_timer_change[2] = 0; + m_timer_change[3] = 0; + + memset(m_reg, 0x00, sizeof(m_reg)); + + m_reg[TMP95C061_P1] = 0x00; + m_reg[TMP95C061_P1CR] = 0x00; + m_reg[TMP95C061_P2] = 0xff; + m_reg[TMP95C061_P2FC] = 0x00; + m_reg[TMP95C061_P5] = 0x3d; + m_reg[TMP95C061_P5CR] = 0x00; + m_reg[TMP95C061_P5FC] = 0x00; + m_reg[TMP95C061_P6] = 0x3b; + m_reg[TMP95C061_P6FC] = 0x00; + m_reg[TMP95C061_P7] = 0xff; + m_reg[TMP95C061_P7CR] = 0x00; + m_reg[TMP95C061_P7FC] = 0x00; + m_reg[TMP95C061_P8] = 0x3f; + m_reg[TMP95C061_P8CR] = 0x00; + m_reg[TMP95C061_P8FC] = 0x00; + m_reg[TMP95C061_PA] = 0x0f; + m_reg[TMP95C061_PACR] = 0x0c; // HACK ngpc needs this but should be zero + m_reg[TMP95C061_PAFC] = 0x0c; // HACK ngpc needs this but should be zero + m_reg[TMP95C061_PB] = 0xff; + m_reg[TMP95C061_PBCR] = 0x00; + m_reg[TMP95C061_PBFC] = 0x00; + m_reg[TMP95C061_MSAR0] = 0xff; + m_reg[TMP95C061_MSAR1] = 0xff; + m_reg[TMP95C061_MSAR2] = 0xff; + m_reg[TMP95C061_MSAR3] = 0xff; + m_reg[TMP95C061_MAMR0] = 0xff; + m_reg[TMP95C061_MAMR1] = 0xff; + m_reg[TMP95C061_MAMR2] = 0xff; + m_reg[TMP95C061_MAMR3] = 0xff; + m_reg[TMP95C061_DREFCR] = 0x00; + m_reg[TMP95C061_DMEMCR] = 0x80; + m_reg[TMP95C061_T01MOD] = 0x00; + m_reg[TMP95C061_T23MOD] = 0x00; + m_reg[TMP95C061_TFFCR] = 0x00; + m_reg[TMP95C061_TRUN] = 0x00; + m_reg[TMP95C061_TRDC] = 0x00; + m_reg[TMP95C061_T4MOD] = 0x20; + m_reg[TMP95C061_T4FFCR] = 0x00; + m_reg[TMP95C061_T5MOD] = 0x20; + m_reg[TMP95C061_T5FFCR] = 0x00; + m_reg[TMP95C061_T45CR] = 0x00; + m_reg[TMP95C061_PG01CR] = 0x00; + m_reg[TMP95C061_PG0REG] = 0x00; + m_reg[TMP95C061_PG1REG] = 0x00; + m_reg[TMP95C061_SC0MOD] = 0x00; + m_reg[TMP95C061_SC0CR] = 0x00; + m_reg[TMP95C061_BR0CR] = 0x00; + m_reg[TMP95C061_SC1MOD] = 0x00; + m_reg[TMP95C061_SC1CR] = 0x00; + m_reg[TMP95C061_BR1CR] = 0x00; + m_reg[TMP95C061_P8FC] = 0x00; + m_reg[TMP95C061_ODE] = 0x00; + m_reg[TMP95C061_ADMOD] = 0x00; + m_reg[TMP95C061_ADREG0L] = 0x3f; + m_reg[TMP95C061_ADREG1L] = 0x3f; + m_reg[TMP95C061_ADREG2L] = 0x3f; + m_reg[TMP95C061_ADREG3L] = 0x3f; + m_reg[TMP95C061_WDMOD] = 0x80; + + for ( i = 0; i < TLCS900_NUM_INPUTS; i++ ) + { + m_level[i] = CLEAR_LINE; + } + m_prefetch_clear = true; +} + + + +#define TMP95C061_NUM_MASKABLE_IRQS 22 +static const struct { + uint8_t reg; + uint8_t iff; + uint8_t vector; +} tmp95c061_irq_vector_map[TMP95C061_NUM_MASKABLE_IRQS] = +{ + { TMP95C061_INTETC32, 0x80, 0x80 }, /* INTTC3 */ + { TMP95C061_INTETC32, 0x08, 0x7c }, /* INTTC2 */ + { TMP95C061_INTETC10, 0x80, 0x78 }, /* INTTC1 */ + { TMP95C061_INTETC10, 0x08, 0x74 }, /* INTTC0 */ + { TMP95C061_INTE0AD, 0x80, 0x70 }, /* INTAD */ + { TMP95C061_INTES1, 0x80, 0x6c }, /* INTTX1 */ + { TMP95C061_INTES1, 0x08, 0x68 }, /* INTRX1 */ + { TMP95C061_INTES0, 0x80, 0x64 }, /* INTTX0 */ + { TMP95C061_INTES0, 0x08, 0x60 }, /* INTRX0 */ + { TMP95C061_INTET76, 0x80, 0x5c }, /* INTTR7 */ + { TMP95C061_INTET76, 0x08, 0x58 }, /* INTTR6 */ + { TMP95C061_INTET54, 0x80, 0x54 }, /* INTTR5 */ + { TMP95C061_INTET54, 0x08, 0x50 }, /* INTTR4 */ + { TMP95C061_INTET32, 0x80, 0x4c }, /* INTT3 */ + { TMP95C061_INTET32, 0x08, 0x48 }, /* INTT2 */ + { TMP95C061_INTET10, 0x80, 0x44 }, /* INTT1 */ + { TMP95C061_INTET10, 0x08, 0x40 }, /* INTT0 */ + /* 0x3c - reserved */ + { TMP95C061_INTE67, 0x80, 0x38 }, /* INT7 */ + { TMP95C061_INTE67, 0x08, 0x34 }, /* INT6 */ + { TMP95C061_INTE45, 0x80, 0x30 }, /* INT5 */ + { TMP95C061_INTE45, 0x08, 0x2c }, /* INT4 */ + { TMP95C061_INTE0AD, 0x08, 0x28 } /* INT0 */ +}; + + +int tmp95c061_device::tlcs900_process_hdma( int channel ) +{ + uint8_t vector = ( m_reg[0x7c + channel] & 0x1f ) << 2; + + /* Check if any HDMA actions should be performed */ + if ( vector >= 0x28 && vector != 0x3C && vector < 0x74 ) + { + int irq = 0; + + while( irq < TMP95C061_NUM_MASKABLE_IRQS && tmp95c061_irq_vector_map[irq].vector != vector ) + irq++; + + /* Check if our interrupt flip-flop is set */ + if ( irq < TMP95C061_NUM_MASKABLE_IRQS && m_reg[tmp95c061_irq_vector_map[irq].reg] & tmp95c061_irq_vector_map[irq].iff ) + { + switch( m_dmam[channel].b.l & 0x1f ) + { + case 0x00: + WRMEM( m_dmad[channel].d, RDMEM( m_dmas[channel].d ) ); + m_dmad[channel].d += 1; + m_cycles += 8; + break; + case 0x01: + WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_dmad[channel].d += 2; + m_cycles += 8; + break; + case 0x02: + WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); + m_dmad[channel].d += 4; + m_cycles += 12; + break; + case 0x04: + WRMEM( m_dmad[channel].d, RDMEM( m_dmas[channel].d ) ); + m_dmad[channel].d -= 1; + m_cycles += 8; + break; + case 0x05: + WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_dmad[channel].d -= 2; + m_cycles += 8; + break; + case 0x06: + WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); + m_dmad[channel].d -= 4; + m_cycles += 12; + break; + case 0x08: + WRMEM( m_dmad[channel].d, RDMEM( m_dmas[channel].d ) ); + m_dmas[channel].d += 1; + m_cycles += 8; + break; + case 0x09: + WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_dmas[channel].d += 2; + m_cycles += 8; + break; + case 0x0a: + WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); + m_dmas[channel].d += 4; + m_cycles += 12; + break; + case 0x0c: + WRMEM( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_dmas[channel].d -= 1; + m_cycles += 8; + break; + case 0x0d: + WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_dmas[channel].d -= 2; + m_cycles += 8; + break; + case 0x0e: + WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); + m_dmas[channel].d -= 4; + m_cycles += 12; + break; + case 0x10: + WRMEM( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_cycles += 8; + break; + case 0x11: + WRMEMW( m_dmad[channel].d, RDMEMW( m_dmas[channel].d ) ); + m_cycles += 8; + break; + case 0x12: + WRMEML( m_dmad[channel].d, RDMEML( m_dmas[channel].d ) ); + m_cycles += 12; + break; + case 0x14: + m_dmas[channel].d += 1; + m_cycles += 5; + break; + } + + m_dmac[channel].w.l -= 1; + + if ( m_dmac[channel].w.l == 0 ) + { + m_reg[0x7c + channel] = 0; + switch( channel ) + { + case 0: + m_reg[TMP95C061_INTETC10] |= 0x08; + break; + case 1: + m_reg[TMP95C061_INTETC10] |= 0x80; + break; + case 2: + m_reg[TMP95C061_INTETC32] |= 0x08; + break; + case 3: + m_reg[TMP95C061_INTETC32] |= 0x80; + break; + } + } + + /* Clear the interrupt flip-flop */ + m_reg[tmp95c061_irq_vector_map[irq].reg] &= ~tmp95c061_irq_vector_map[irq].iff; + + return 1; + } + } + return 0; +} + + +void tmp95c061_device::tlcs900_check_hdma() +{ + /* HDMA can only be performed if interrupts are allowed */ + if ( ( m_sr.b.h & 0x70 ) != 0x70 ) + { + if ( ! tlcs900_process_hdma( 0 ) ) + { + if ( ! tlcs900_process_hdma( 1 ) ) + { + if ( ! tlcs900_process_hdma( 2 ) ) + { + tlcs900_process_hdma( 3 ); + } + } + } + } +} + + +void tmp95c061_device::tlcs900_check_irqs() +{ + int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + int level = 0; + int irq = -1; + int i; + + /* Check for NMI */ + if ( m_nmi_state == ASSERT_LINE ) + { + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + m_pc.d = RDMEML( 0xffff00 + 0x20 ); + m_cycles += 18; + m_prefetch_clear = true; + + m_halted = 0; + + m_nmi_state = CLEAR_LINE; + + return; + } + + /* Check regular irqs */ + for( i = 0; i < TMP95C061_NUM_MASKABLE_IRQS; i++ ) + { + if ( m_reg[tmp95c061_irq_vector_map[i].reg] & tmp95c061_irq_vector_map[i].iff ) + { + switch( tmp95c061_irq_vector_map[i].iff ) + { + case 0x80: + irq_vectors[ ( m_reg[ tmp95c061_irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i; + break; + case 0x08: + irq_vectors[ m_reg[ tmp95c061_irq_vector_map[i].reg ] & 0x07 ] = i; + break; + } + } + } + + /* Check highest allowed priority irq */ + for ( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) + { + if ( irq_vectors[i] >= 0 ) + { + irq = irq_vectors[i]; + level = i + 1; + } + } + + /* Take irq */ + if ( irq >= 0 ) + { + uint8_t vector = tmp95c061_irq_vector_map[irq].vector; + + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + + /* Mask off any lower priority interrupts */ + m_sr.b.h = ( m_sr.b.h & 0x8f ) | ( level << 4 ); + + m_pc.d = RDMEML( 0xffff00 + vector ); + m_cycles += 18; + m_prefetch_clear = true; + + m_halted = 0; + + /* Clear taken IRQ */ + m_reg[ tmp95c061_irq_vector_map[irq].reg ] &= ~ tmp95c061_irq_vector_map[irq].iff; + } +} + + +void tmp95c061_device::tlcs900_handle_ad() +{ + if ( m_ad_cycles_left > 0 ) + { + m_ad_cycles_left -= m_cycles; + if ( m_ad_cycles_left <= 0 ) + { + /* Store A/D converted value */ + switch( m_reg[TMP95C061_ADMOD] & 0x03 ) + { + case 0x00: /* AN0 */ + m_reg[TMP95C061_ADREG0L] |= 0xc0; + m_reg[TMP95C061_ADREG0H] = 0xff; + break; + case 0x01: /* AN1 */ + case 0x02: /* AN2 */ + case 0x03: /* AN3 */ + break; + } + + /* Clear BUSY flag, set END flag */ + m_reg[TMP95C061_ADMOD] &= ~ 0x40; + m_reg[TMP95C061_ADMOD] |= 0x80; + + m_reg[TMP95C061_INTE0AD] |= 0x80; + m_check_irqs = 1; + } + } +} + + +enum ff_change +{ + FF_CLEAR, + FF_SET, + FF_INVERT +}; + + +void tmp95c061_device::tlcs900_change_tff( int which, int change ) +{ + switch( which ) + { + case 1: + switch( change ) + { + case FF_CLEAR: + m_to1 = 0; + break; + case FF_SET: + m_to1 = 1; + break; + case FF_INVERT: + m_to1 ^= 1; + break; + } + break; + + case 3: + switch( change ) + { + case FF_CLEAR: + m_to3 = 0; + break; + case FF_SET: + m_to3 = 1; + break; + case FF_INVERT: + m_to3 ^= 1; + break; + } + break; + } + + update_porta(); +} + + +void tmp95c061_device::tlcs900_handle_timers() +{ + uint32_t old_pre = m_timer_pre; + + /* Is the pre-scaler active */ + if ( m_reg[TMP95C061_TRUN] & 0x80 ) + m_timer_pre += m_cycles; + + /* Timer 0 */ + if ( m_reg[TMP95C061_TRUN] & 0x01 ) + { + switch( m_reg[TMP95C061_T01MOD] & 0x03 ) + { + case 0x00: /* TIO */ + break; + case 0x01: /* T1 */ + m_timer_change[0] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T4 */ + m_timer_change[0] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); + break; + case 0x03: /* T16 */ + m_timer_change[0] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; m_timer_change[0] > 0; m_timer_change[0]-- ) + { +//printf("timer0 = %02x, TREG0 = %02x\n", m_timer[0], m_reg[TREG0] ); + m_timer[0] += 1; + if ( m_timer[0] == m_reg[TMP95C061_TREG0] ) + { + if ( ( m_reg[TMP95C061_T01MOD] & 0x0c ) == 0x00 ) + { + m_timer_change[1] += 1; + } + + /* In 16bit timer mode the timer should not be reset */ + if ( ( m_reg[TMP95C061_T01MOD] & 0xc0 ) != 0x40 ) + { + m_timer[0] = 0; + m_reg[TMP95C061_INTET10] |= 0x08; + } + } + } + } + + /* Timer 1 */ + if ( m_reg[TMP95C061_TRUN] & 0x02 ) + { + switch( ( m_reg[TMP95C061_T01MOD] >> 2 ) & 0x03 ) + { + case 0x00: /* TO0TRG */ + break; + case 0x01: /* T1 */ + m_timer_change[1] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T16 */ + m_timer_change[1] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + case 0x03: /* T256 */ + m_timer_change[1] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); + break; + } + + for( ; m_timer_change[1] > 0; m_timer_change[1]-- ) + { + m_timer[1] += 1; + if ( m_timer[1] == m_reg[TMP95C061_TREG1] ) + { + m_timer[1] = 0; + m_reg[TMP95C061_INTET10] |= 0x80; + + if ( m_reg[TMP95C061_TFFCR] & 0x02 ) + { + tlcs900_change_tff( 1, FF_INVERT ); + } + + /* In 16bit timer mode also reset timer 0 */ + if ( ( m_reg[TMP95C061_T01MOD] & 0xc0 ) == 0x40 ) + { + m_timer[0] = 0; + } + } + } + } + + /* Timer 2 */ + if ( m_reg[TMP95C061_TRUN] & 0x04 ) + { + switch( m_reg[TMP95C061_T23MOD] & 0x03 ) + { + case 0x00: /* invalid */ + case 0x01: /* T1 */ + m_timer_change[2] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T4 */ + m_timer_change[2] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); + break; + case 0x03: /* T16 */ + m_timer_change[2] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; m_timer_change[2] > 0; m_timer_change[2]-- ) + { + m_timer[2] += 1; + if ( m_timer[2] == m_reg[TMP95C061_TREG2] ) + { + if ( ( m_reg[TMP95C061_T23MOD] & 0x0c ) == 0x00 ) + { + m_timer_change[3] += 1; + } + + /* In 16bit timer mode the timer should not be reset */ + if ( ( m_reg[TMP95C061_T23MOD] & 0xc0 ) != 0x40 ) + { + m_timer[2] = 0; + m_reg[TMP95C061_INTET32] |= 0x08; + } + } + } + } + + /* Timer 3 */ + if ( m_reg[TMP95C061_TRUN] & 0x08 ) + { + switch( ( m_reg[TMP95C061_T23MOD] >> 2 ) & 0x03 ) + { + case 0x00: /* TO2TRG */ + break; + case 0x01: /* T1 */ + m_timer_change[3] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T16 */ + m_timer_change[3] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + case 0x03: /* T256 */ + m_timer_change[3] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); + break; + } + + for( ; m_timer_change[3] > 0; m_timer_change[3]-- ) + { + m_timer[3] += 1; + if ( m_timer[3] == m_reg[TMP95C061_TREG3] ) + { + m_timer[3] = 0; + m_reg[TMP95C061_INTET32] |= 0x80; + + if ( m_reg[TMP95C061_TFFCR] & 0x20 ) + { + tlcs900_change_tff( 3, FF_INVERT ); + } + + /* In 16bit timer mode also reset timer 2 */ + if ( ( m_reg[TMP95C061_T23MOD] & 0xc0 ) == 0x40 ) + { + m_timer[2] = 0; + } + } + } + } + + m_timer_pre &= 0xffffff; +} + + +void tmp95c061_device::execute_set_input(int input, int level) +{ + switch( input ) + { + case INPUT_LINE_NMI: + case TLCS900_NMI: + if ( m_level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_nmi_state = level; + } + m_level[TLCS900_NMI] = level; + break; + + case TLCS900_INTWD: + break; + + case TLCS900_INT0: + /* Is INT0 functionality enabled? */ + if ( m_reg[TMP95C061_IIMC] & 0x04 ) + { + if ( m_reg[TMP95C061_IIMC] & 0x02 ) + { + /* Rising edge detect */ + if ( m_level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE ) + { + /* Leave HALT state */ + m_halted = 0; + m_reg[TMP95C061_INTE0AD] |= 0x08; + } + } + else + { + /* Level detect */ + if ( level == ASSERT_LINE ) + m_reg[TMP95C061_INTE0AD] |= 0x08; + else + m_reg[TMP95C061_INTE0AD] &= ~ 0x08; + } + } + m_level[TLCS900_INT0] = level; + break; + + case TLCS900_INT4: + if ( ! ( m_reg[TMP95C061_PBCR] & 0x01 ) ) + { + if ( m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_reg[TMP95C061_INTE45] |= 0x08; + } + } + m_level[TLCS900_INT4] = level; + break; + + case TLCS900_INT5: + if ( ! ( m_reg[TMP95C061_PBCR] & 0x02 ) ) + { + if ( m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_reg[TMP95C061_INTE45] |= 0x80; + } + } + m_level[TLCS900_INT5] = level; + break; + + case TLCS900_TIO: /* External timer input for timer 0 */ + if ( ( m_reg[TMP95C061_TRUN] & 0x01 ) && ( m_reg[TMP95C061_T01MOD] & 0x03 ) == 0x00 ) + { + if ( m_level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_timer_change[0] += 1; + } + } + m_level[TLCS900_TIO] = level; + break; + } + m_check_irqs = 1; +} + + +uint8_t tmp95c061_device::internal_r(offs_t offset) +{ + switch (offset) + { + case TMP95C061_P1: m_reg[offset] = m_port1_read(0); break; + case TMP95C061_P5: m_reg[offset] = m_port5_read(0); break; + case TMP95C061_P6: m_reg[offset] = m_port6_read(0); break; + case TMP95C061_P7: m_reg[offset] = m_port7_read(0); break; + case TMP95C061_P8: m_reg[offset] = m_port8_read(0); break; + case TMP95C061_P9: m_reg[offset] = m_port9_read(0); break; + case TMP95C061_PA: m_reg[offset] = m_porta_read(0); break; + case TMP95C061_PB: m_reg[offset] = m_portb_read(0); break; + } + return m_reg[ offset ]; +} + + +void tmp95c061_device::update_porta() +{ + int fc = (m_to1 << 2) | (m_to3 << 3); + + m_porta_write(0, ((fc & m_reg[TMP95C061_PAFC]) | (m_reg[TMP95C061_PA] & ~m_reg[TMP95C061_PAFC])) & m_reg[TMP95C061_PACR], 0xff); +} + +void tmp95c061_device::internal_w(offs_t offset, uint8_t data) +{ + switch ( offset ) + { + case TMP95C061_TRUN: + if ( ! ( data & 0x01 ) ) + { + m_timer[0] = 0; + m_timer_change[0] = 0; + } + if ( ! ( data & 0x02 ) ) + { + m_timer[1] = 0; + m_timer_change[1] = 0; + } + if ( ! ( data & 0x04 ) ) + { + m_timer[2] = 0; + m_timer_change[2] = 0; + } + if ( ! ( data & 0x08 ) ) + { + m_timer[3] = 0; + m_timer_change[3] = 0; + } + if ( ! ( data & 0x10 ) ) + m_timer[4] = 0; + if ( ! ( data & 0x20 ) ) + m_timer[5] = 0; + break; + + case TMP95C061_TFFCR: + switch( data & 0x0c ) + { + case 0x00: + tlcs900_change_tff( 1, FF_INVERT ); + break; + case 0x04: + tlcs900_change_tff( 1, FF_SET ); + break; + case 0x08: + tlcs900_change_tff( 1, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + tlcs900_change_tff( 3, FF_INVERT ); + break; + case 0x40: + tlcs900_change_tff( 3, FF_SET ); + break; + case 0x80: + tlcs900_change_tff( 3, FF_CLEAR ); + break; + } + break; + case TMP95C061_MSAR0: + case TMP95C061_MAMR0: + case TMP95C061_MSAR1: + case TMP95C061_MAMR1: + break; + + case TMP95C061_SC0BUF: + // Fake finish sending data + m_reg[TMP95C061_INTES0] |= 0x80; + break; + + case TMP95C061_ADMOD: + /* Preserve read-only bits */ + data = ( m_reg[TMP95C061_ADMOD] & 0xc0 ) | ( data & 0x3f ); + + /* Check for A/D request start */ + if ( data & 0x04 ) + { + data &= ~0x04; + data |= 0x40; + m_ad_cycles_left = ( data & 0x08 ) ? 640 : 320; + } + break; + + case TMP95C061_WDMOD: + case TMP95C061_WDCR: + break; + + case TMP95C061_INTE0AD: + case TMP95C061_INTE45: + case TMP95C061_INTE67: + case TMP95C061_INTET10: + case TMP95C061_INTET32: + case TMP95C061_INTET54: + case TMP95C061_INTET76: + case TMP95C061_INTES0: + case TMP95C061_INTES1: + case TMP95C061_INTETC10: + case TMP95C061_INTETC32: + if ( data & 0x80 ) + data = ( data & 0x7f ) | ( m_reg[offset] & 0x80 ); + if ( data & 0x08 ) + data = ( data & 0xf7 ) | ( m_reg[offset] & 0x08 ); + break; + + case TMP95C061_IIMC: + break; + + default: + break; + } + + m_check_irqs = 1; + m_reg[ offset ] = data; + + switch(offset) + { + case TMP95C061_P1: m_port1_write(0, data, 0xff); break; + case TMP95C061_P2: m_port2_write(0, data, 0xff); break; + case TMP95C061_P5: m_port5_write(0, data, 0xff); break; + case TMP95C061_P6: m_port6_write(0, data, 0xff); break; + case TMP95C061_P7: m_port7_write(0, data, 0xff); break; + case TMP95C061_P8: m_port8_write(0, data, 0xff); break; + + case TMP95C061_PA: + case TMP95C061_PACR: + case TMP95C061_PAFC: + update_porta(); + break; + } +} diff --git a/src/devices/cpu/tlcs900/tmp95c061.h b/src/devices/cpu/tlcs900/tmp95c061.h new file mode 100644 index 00000000000..bb10853dadd --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp95c061.h @@ -0,0 +1,96 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol + +#ifndef MAME_CPU_TLCS900_TMP95C061_H +#define MAME_CPU_TLCS900_TMP95C061_H + +#pragma once + +#include "tlcs900.h" + +DECLARE_DEVICE_TYPE(TMP95C061, tmp95c061_device) + + +class tmp95c061_device : public tlcs900h_device +{ +public: + // construction/destruction + tmp95c061_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // configuration helpers + auto port1_read() { return m_port1_read.bind(); } + auto port1_write() { return m_port1_write.bind(); } + auto port2_write() { return m_port2_write.bind(); } + auto port5_read() { return m_port5_read.bind(); } + auto port5_write() { return m_port5_write.bind(); } + auto port6_write() { return m_port6_write.bind(); } + auto port7_read() { return m_port7_read.bind(); } + auto port7_write() { return m_port7_write.bind(); } + auto port8_read() { return m_port8_read.bind(); } + auto port8_write() { return m_port8_write.bind(); } + auto port9_read() { return m_port9_read.bind(); } + auto porta_read() { return m_porta_read.bind(); } + auto porta_write() { return m_porta_write.bind(); } + auto portb_read() { return m_portb_read.bind(); } + auto portb_write() { return m_portb_write.bind(); } + +protected: + virtual void device_config_complete() override; + virtual void device_start() override; + virtual void device_reset() override; + + virtual void execute_set_input(int inputnum, int state) override; + virtual void tlcs900_check_hdma() override; + virtual void tlcs900_check_irqs() override; + virtual void tlcs900_handle_ad() override; + virtual void tlcs900_handle_timers() override; + + void tlcs900_change_tff( int which, int change ); + int tlcs900_process_hdma( int channel ); + void update_porta(); + +private: + uint8_t internal_r(offs_t offset); + void internal_w(offs_t offset, uint8_t data); + + void internal_mem(address_map &map); + + uint8_t m_to1; + uint8_t m_to3; + + // Port 1: 8 bit I/O. Shared with D8-D15 + devcb_read8 m_port1_read; + devcb_write8 m_port1_write; + + // Port 2: 8 bit output only. Shared with A16-A23 + devcb_write8 m_port2_write; + + // Port 5: 4 bit I/O. Shared with HWR, BUSRQ, BUSAK, RW + devcb_read8 m_port5_read; + devcb_write8 m_port5_write; + + // Port 6: 6 bit I/O. Shared with CS0, CS1, CS3/LCAS, RAS, REFOUT + devcb_read8 m_port6_read; + devcb_write8 m_port6_write; + + // Port 7: 8 bit I/O. Shared with PG0-OUT, PG1-OUT + devcb_read8 m_port7_read; + devcb_write8 m_port7_write; + + // Port 8: 6 bit I/O. Shared with TXD0, TXD1, RXD0, RXD1, CTS0, SCLK0, SCLK1 + devcb_read8 m_port8_read; + devcb_write8 m_port8_write; + + // Port 9: 4 bit input only. Shared with AN0-AN3 + devcb_read8 m_port9_read; + + // Port A: 4 bit I/O. Shared with WAIT, TI0, TO1, TO2 + devcb_read8 m_porta_read; + devcb_write8 m_porta_write; + + // Port B: 8 bit I/O. Shared with TI4/INT4, TI5/INT5, TI6/INT6, TI7/INT7, TO4, TO5, TO6 + devcb_read8 m_portb_read; + devcb_write8 m_portb_write; +}; + +#endif // MAME_CPU_TLCS900_TMP95C061_H diff --git a/src/devices/cpu/tlcs900/tmp95c063.cpp b/src/devices/cpu/tlcs900/tmp95c063.cpp new file mode 100644 index 00000000000..0bede30f7a2 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp95c063.cpp @@ -0,0 +1,1129 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +/******************************************************************* + +Toshiba TMP95C063 emulation + +*******************************************************************/ + +#include "emu.h" +#include "tmp95c063.h" + +DEFINE_DEVICE_TYPE(TMP95C063, tmp95c063_device, "tmp95c063", "Toshiba TMP95C063") + + +tmp95c063_device::tmp95c063_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + tlcs900h_device(mconfig, TMP95C063, tag, owner, clock), + m_port1_read(*this), + m_port1_write(*this), + m_port2_write(*this), + m_port5_read(*this), + m_port5_write(*this), + m_port6_read(*this), + m_port6_write(*this), + m_port7_read(*this), + m_port7_write(*this), + m_port8_read(*this), + m_port8_write(*this), + m_port9_read(*this), + m_port9_write(*this), + m_porta_read(*this), + m_porta_write(*this), + m_portb_read(*this), + m_portb_write(*this), + m_portc_read(*this), + m_portd_read(*this), + m_portd_write(*this), + m_porte_read(*this), + m_porte_write(*this), + m_an_read(*this) +{ +} + +void tmp95c063_device::internal_mem(address_map &map) +{ + map(0x000000, 0x00009f).rw(FUNC(tmp95c063_device::internal_r), FUNC(tmp95c063_device::internal_w)); +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void tmp95c063_device::device_config_complete() +{ + if (m_am8_16 == 0) + { + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 16, 24, 0, address_map_constructor(FUNC(tmp95c063_device::internal_mem), this)); + } + else + { + m_program_config = address_space_config("program", ENDIANNESS_LITTLE, 8, 24, 0, address_map_constructor(FUNC(tmp95c063_device::internal_mem), this)); + } +} + + +/* TMP95C063 Internal register defines */ + +#define TMP95C063_P1 0x01 +#define TMP95C063_P1CR 0x04 +#define TMP95C063_P2 0x06 +#define TMP95C063_P2FC 0x09 +#define TMP95C063_P5 0x0d +#define TMP95C063_P5CR 0x10 +#define TMP95C063_P5FC 0x11 +#define TMP95C063_P6 0x12 +#define TMP95C063_P7 0x13 +#define TMP95C063_P6FC 0x15 +#define TMP95C063_P7CR 0x16 +#define TMP95C063_P7FC 0x17 +#define TMP95C063_P8 0x18 +#define TMP95C063_P9 0x19 +#define TMP95C063_P8CR 0x1a +#define TMP95C063_P8FC 0x1b +#define TMP95C063_P9CR 0x1c +#define TMP95C063_P9FC 0x1d +#define TMP95C063_PA 0x1e +#define TMP95C063_PB 0x1f +#define TMP95C063_T8RUN 0x20 +#define TMP95C063_TRDC 0x21 +#define TMP95C063_TREG0 0x22 +#define TMP95C063_TREG1 0x23 +#define TMP95C063_T01MOD 0x24 +#define TMP95C063_T02FFCR 0x25 +#define TMP95C063_TREG2 0x26 +#define TMP95C063_TREG3 0x27 +#define TMP95C063_T23MOD 0x28 +#define TMP95C063_TREG4 0x29 +#define TMP95C063_TREG5 0x2a +#define TMP95C063_T45MOD 0x2b +#define TMP95C063_T46FFCR 0x2c +#define TMP95C063_TREG6 0x2d +#define TMP95C063_TREG7 0x2e +#define TMP95C063_T67MOD 0x2f +#define TMP95C063_TREG8L 0x30 +#define TMP95C063_TREG8H 0x31 +#define TMP95C063_TREG9L 0x32 +#define TMP95C063_TREG9H 0x33 +#define TMP95C063_CAP1L 0x34 +#define TMP95C063_CAP1H 0x35 +#define TMP95C063_CAP2L 0x36 +#define TMP95C063_CAP2H 0x37 +#define TMP95C063_T8MOD 0x38 +#define TMP95C063_T8FFCR 0x39 +#define TMP95C063_T89CR 0x3a +#define TMP95C063_T16RUN 0x3b +#define TMP95C063_TREGAL 0x40 +#define TMP95C063_TREGAH 0x41 +#define TMP95C063_TREGBL 0x42 +#define TMP95C063_TREGBH 0x43 +#define TMP95C063_CAP3L 0x44 +#define TMP95C063_CAP3H 0x45 +#define TMP95C063_CAP4L 0x46 +#define TMP95C063_CAP4H 0x47 +#define TMP95C063_T9MOD 0x48 +#define TMP95C063_T9FFCR 0x49 +#define TMP95C063_DAREG0 0x4a +#define TMP95C063_DAREG1 0x4b +#define TMP95C063_PG0REG 0x4c +#define TMP95C063_PG1REG 0x4d +#define TMP95C063_PG01CR 0x4e +#define TMP95C063_DADRV 0x4f +#define TMP95C063_SC0BUF 0x50 +#define TMP95C063_SC0CR 0x51 +#define TMP95C063_SC0MOD 0x52 +#define TMP95C063_BR0CR 0x53 +#define TMP95C063_SC1BUF 0x54 +#define TMP95C063_SC1CR 0x55 +#define TMP95C063_SC1MOD 0x56 +#define TMP95C063_BR1CR 0x57 +#define TMP95C063_ODE 0x58 +#define TMP95C063_DMA0V 0x5a +#define TMP95C063_DMA1V 0x5b +#define TMP95C063_DMA2V 0x5c +#define TMP95C063_DMA3V 0x5d +#define TMP95C063_ADMOD1 0x5e +#define TMP95C063_ADMOD2 0x5f +#define TMP95C063_ADREG04L 0x60 +#define TMP95C063_ADREG04H 0x61 +#define TMP95C063_ADREG15L 0x62 +#define TMP95C063_ADREG15H 0x63 +#define TMP95C063_ADREG26L 0x64 +#define TMP95C063_ADREG26H 0x65 +#define TMP95C063_ADREG37L 0x66 +#define TMP95C063_ADREG37H 0x67 +#define TMP95C063_SDMACR0 0x6a +#define TMP95C063_SDMACR1 0x6b +#define TMP95C063_SDMACR2 0x6c +#define TMP95C063_SDMACR3 0x6d +#define TMP95C063_WDMOD 0x6e +#define TMP95C063_WDCR 0x6f +#define TMP95C063_INTE0AD 0x70 +#define TMP95C063_INTE12 0x71 +#define TMP95C063_INTE34 0x72 +#define TMP95C063_INTE56 0x73 +#define TMP95C063_INTE78 0x74 +#define TMP95C063_INTET01 0x75 +#define TMP95C063_INTET23 0x76 +#define TMP95C063_INTET45 0x77 +#define TMP95C063_INTET67 0x78 +#define TMP95C063_INTET89 0x79 +#define TMP95C063_INTETAB 0x7a +#define TMP95C063_INTES0 0x7b +#define TMP95C063_INTES1 0x7c +#define TMP95C063_INTETC01 0x7d +#define TMP95C063_INTETC23 0x7e +#define TMP95C063_IIMC 0x7f +#define TMP95C063_PACR 0x80 +#define TMP95C063_PAFC 0x81 +#define TMP95C063_PBCR 0x82 +#define TMP95C063_PBFC 0x83 +#define TMP95C063_PC 0x84 +#define TMP95C063_PD 0x85 +#define TMP95C063_PDCR 0x88 +#define TMP95C063_PE 0x8a +#define TMP95C063_PECR 0x8c +#define TMP95C063_BEXCS 0x8f +#define TMP95C063_B0CS 0x90 +#define TMP95C063_B1CS 0x91 +#define TMP95C063_B2CS 0x92 +#define TMP95C063_B3CS 0x93 +#define TMP95C063_MSAR0 0x94 +#define TMP95C063_MAMR0 0x95 +#define TMP95C063_MSAR1 0x96 +#define TMP95C063_MAMR1 0x97 +#define TMP95C063_MSAR2 0x98 +#define TMP95C063_MAMR2 0x99 +#define TMP95C063_MSAR3 0x9a +#define TMP95C063_MAMR3 0x9b +#define TMP95C063_DREFCR1 0x9c +#define TMP95C063_DMEMCR1 0x9d +#define TMP95C063_DREFCR3 0x9e +#define TMP95C063_DMEMCR3 0x9f + + +#define TMP95C063_NUM_MASKABLE_IRQS 30 +static const struct { + uint8_t reg; + uint8_t iff; + uint8_t vector; +} tmp95c063_irq_vector_map[TMP95C063_NUM_MASKABLE_IRQS] = +{ + { TMP95C063_INTETC23, 0x80, 0xa0 }, /* INTTC3 */ + { TMP95C063_INTETC23, 0x08, 0x9c }, /* INTTC2 */ + { TMP95C063_INTETC01, 0x80, 0x98 }, /* INTTC1 */ + { TMP95C063_INTETC01, 0x08, 0x94 }, /* INTTC0 */ + { TMP95C063_INTE0AD, 0x80, 0x90 }, /* INTAD */ + { TMP95C063_INTES1, 0x80, 0x8c }, /* INTTX1 */ + { TMP95C063_INTES1, 0x08, 0x88 }, /* INTRX1 */ + { TMP95C063_INTES0, 0x80, 0x84 }, /* INTTX0 */ + { TMP95C063_INTES0, 0x08, 0x80 }, /* INTRX0 */ + { TMP95C063_INTETAB, 0x80, 0x7c }, /* INTTRB */ + { TMP95C063_INTETAB, 0x08, 0x78 }, /* INTTRA */ + { TMP95C063_INTET89, 0x80, 0x74 }, /* INTTR9 */ + { TMP95C063_INTET89, 0x80, 0x70 }, /* INTTR8 */ + { TMP95C063_INTET67, 0x80, 0x6c }, /* INTT7 */ + { TMP95C063_INTET67, 0x08, 0x68 }, /* INTT6 */ + { TMP95C063_INTET45, 0x80, 0x64 }, /* INTT5 */ + { TMP95C063_INTET45, 0x08, 0x60 }, /* INTT4 */ + { TMP95C063_INTET23, 0x80, 0x5c }, /* INTT3 */ + { TMP95C063_INTET23, 0x08, 0x58 }, /* INTT2 */ + { TMP95C063_INTET01, 0x80, 0x54 }, /* INTT1 */ + { TMP95C063_INTET01, 0x08, 0x50 }, /* INTT0 */ + { TMP95C063_INTE78, 0x80, 0x4c }, /* int8_t */ + { TMP95C063_INTE78, 0x08, 0x48 }, /* INT7 */ + { TMP95C063_INTE56, 0x80, 0x44 }, /* INT6 */ + { TMP95C063_INTE56, 0x08, 0x40 }, /* INT5 */ + /* 0x3c - reserved */ + { TMP95C063_INTE34, 0x80, 0x38 }, /* INT4 */ + { TMP95C063_INTE34, 0x08, 0x34 }, /* INT3 */ + { TMP95C063_INTE12, 0x80, 0x30 }, /* INT2 */ + { TMP95C063_INTE12, 0x08, 0x2c }, /* INT1 */ + { TMP95C063_INTE0AD, 0x08, 0x28 } /* INT0 */ +}; + +void tmp95c063_device::tlcs900_handle_timers() +{ + // TODO: implement timers 4-7 + + uint32_t old_pre = m_timer_pre; + + /* Is the pre-scaler active */ + if ( m_reg[TMP95C063_T8RUN] & 0x80 ) + m_timer_pre += m_cycles; + + /* Timer 0 */ + if ( m_reg[TMP95C063_T8RUN] & 0x01 ) + { + switch( m_reg[TMP95C063_T01MOD] & 0x03 ) + { + case 0x00: /* TIO */ + break; + case 0x01: /* T1 */ + m_timer_change[0] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T4 */ + m_timer_change[0] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); + break; + case 0x03: /* T16 */ + m_timer_change[0] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; m_timer_change[0] > 0; m_timer_change[0]-- ) + { +//printf("timer0 = %02x, TREG0 = %02x\n", m_timer[0], m_reg[TREG0] ); + m_timer[0] += 1; + if ( m_timer[0] == m_reg[TMP95C063_TREG0] ) + { + if ( ( m_reg[TMP95C063_T01MOD] & 0x0c ) == 0x00 ) + { + m_timer_change[1] += 1; + } + + /* In 16bit timer mode the timer should not be reset */ + if ( ( m_reg[TMP95C063_T01MOD] & 0xc0 ) != 0x40 ) + { + m_timer[0] = 0; + m_reg[TMP95C063_INTET01] |= 0x08; + } + } + } + } + + /* Timer 1 */ + if ( m_reg[TMP95C063_T8RUN] & 0x02 ) + { + switch( ( m_reg[TMP95C063_T01MOD] >> 2 ) & 0x03 ) + { + case 0x00: /* TO0TRG */ + break; + case 0x01: /* T1 */ + m_timer_change[1] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T16 */ + m_timer_change[1] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + case 0x03: /* T256 */ + m_timer_change[1] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); + break; + } + + for( ; m_timer_change[1] > 0; m_timer_change[1]-- ) + { + m_timer[1] += 1; + if ( m_timer[1] == m_reg[TMP95C063_TREG1] ) + { + m_timer[1] = 0; + m_reg[TMP95C063_INTET01] |= 0x80; + + if ( m_reg[TMP95C063_T02FFCR] & 0x02 ) + { + //tlcs900_change_tff( 1, FF_INVERT ); + } + + /* In 16bit timer mode also reset timer 0 */ + if ( ( m_reg[TMP95C063_T01MOD] & 0xc0 ) == 0x40 ) + { + m_timer[0] = 0; + } + } + } + } + + /* Timer 2 */ + if ( m_reg[TMP95C063_T8RUN] & 0x04 ) + { + switch( m_reg[TMP95C063_T23MOD] & 0x03 ) + { + case 0x00: /* invalid */ + case 0x01: /* T1 */ + m_timer_change[2] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T4 */ + m_timer_change[2] += ( m_timer_pre >> 9 ) - ( old_pre >> 9 ); + break; + case 0x03: /* T16 */ + m_timer_change[2] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + } + + for( ; m_timer_change[2] > 0; m_timer_change[2]-- ) + { + m_timer[2] += 1; + if ( m_timer[2] == m_reg[TMP95C063_TREG2] ) + { + if ( ( m_reg[TMP95C063_T23MOD] & 0x0c ) == 0x00 ) + { + m_timer_change[3] += 1; + } + + /* In 16bit timer mode the timer should not be reset */ + if ( ( m_reg[TMP95C063_T23MOD] & 0xc0 ) != 0x40 ) + { + m_timer[2] = 0; + m_reg[TMP95C063_INTET23] |= 0x08; + } + } + } + } + + /* Timer 3 */ + if ( m_reg[TMP95C063_T8RUN] & 0x08 ) + { + switch( ( m_reg[TMP95C063_T23MOD] >> 2 ) & 0x03 ) + { + case 0x00: /* TO2TRG */ + break; + case 0x01: /* T1 */ + m_timer_change[3] += ( m_timer_pre >> 7 ) - ( old_pre >> 7 ); + break; + case 0x02: /* T16 */ + m_timer_change[3] += ( m_timer_pre >> 11 ) - ( old_pre >> 11 ); + break; + case 0x03: /* T256 */ + m_timer_change[3] += ( m_timer_pre >> 15 ) - ( old_pre >> 15 ); + break; + } + + for( ; m_timer_change[3] > 0; m_timer_change[3]-- ) + { + m_timer[3] += 1; + if ( m_timer[3] == m_reg[TMP95C063_TREG3] ) + { + m_timer[3] = 0; + m_reg[TMP95C063_INTET23] |= 0x80; + + if ( m_reg[TMP95C063_T02FFCR] & 0x20 ) + { + //tlcs900_change_tff( 3, FF_INVERT ); + } + + /* In 16bit timer mode also reset timer 2 */ + if ( ( m_reg[TMP95C063_T23MOD] & 0xc0 ) == 0x40 ) + { + m_timer[2] = 0; + } + } + } + } + + m_timer_pre &= 0xffffff; +} + +void tmp95c063_device::tlcs900_check_hdma() +{ + // TODO +} + +void tmp95c063_device::tlcs900_check_irqs() +{ + int irq_vectors[9] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + int level = 0; + int irq = -1; + int i; + + /* Check for NMI */ + if ( m_nmi_state == ASSERT_LINE ) + { + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + m_pc.d = RDMEML( 0xffff00 + 0x20 ); + m_cycles += 18; + m_prefetch_clear = true; + + m_halted = 0; + + m_nmi_state = CLEAR_LINE; + + return; + } + + /* Check regular irqs */ + for( i = 0; i < TMP95C063_NUM_MASKABLE_IRQS; i++ ) + { + if ( m_reg[tmp95c063_irq_vector_map[i].reg] & tmp95c063_irq_vector_map[i].iff ) + { + switch( tmp95c063_irq_vector_map[i].iff ) + { + case 0x80: + irq_vectors[ ( m_reg[ tmp95c063_irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i; + break; + case 0x08: + irq_vectors[ m_reg[ tmp95c063_irq_vector_map[i].reg ] & 0x07 ] = i; + break; + } + } + } + + /* Check highest allowed priority irq */ + for ( i = std::max( 1, ( ( m_sr.b.h & 0x70 ) >> 4 ) ); i < 7; i++ ) + { + if ( irq_vectors[i] >= 0 ) + { + irq = irq_vectors[i]; + level = i + 1; + } + } + + /* Take irq */ + if ( irq >= 0 ) + { + uint8_t vector = tmp95c063_irq_vector_map[irq].vector; + + m_xssp.d -= 4; + WRMEML( m_xssp.d, m_pc.d ); + m_xssp.d -= 2; + WRMEMW( m_xssp.d, m_sr.w.l ); + + /* Mask off any lower priority interrupts */ + m_sr.b.h = ( m_sr.b.h & 0x8f ) | ( level << 4 ); + + m_pc.d = RDMEML( 0xffff00 + vector ); + m_cycles += 18; + m_prefetch_clear = true; + + m_halted = 0; + + /* Clear taken IRQ */ + m_reg[ tmp95c063_irq_vector_map[irq].reg ] &= ~ tmp95c063_irq_vector_map[irq].iff; + } +} + + +void tmp95c063_device::tlcs900_handle_ad() +{ + if ( m_ad_cycles_left > 0 ) + { + m_ad_cycles_left -= m_cycles; + if ( m_ad_cycles_left <= 0 ) + { + int ad_value; + + /* Store A/D converted value */ + if ((m_reg[TMP95C063_ADMOD1] & 0x10) == 0) // conversion channel fixed + { + switch( m_reg[TMP95C063_ADMOD2] & 0x07 ) + { + case 0x00: // AN0 + ad_value = m_an_read[0](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + break; + case 0x01: // AN1 + ad_value = m_an_read[1](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + break; + case 0x02: // AN2 + ad_value = m_an_read[2](0) & 0x3ff; + m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; + break; + case 0x03: // AN3 + ad_value = m_an_read[3](0) & 0x3ff; + m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; + break; + case 0x04: // AN4 + ad_value = m_an_read[4](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + break; + case 0x05: // AN5 + ad_value = m_an_read[5](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + break; + case 0x06: // AN6 + ad_value = m_an_read[6](0) & 0x3ff; + m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; + break; + case 0x07: // AN7 + ad_value = m_an_read[7](0) & 0x3ff; + m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; + break; + } + } + else // conversion channel sweep + { + switch( m_reg[TMP95C063_ADMOD2] & 0x07 ) + { + case 0x00: // AN0 + ad_value = m_an_read[0](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + break; + case 0x01: // AN0 -> AN1 + ad_value = m_an_read[0](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[1](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + break; + case 0x02: // AN0 -> AN1 -> AN2 + ad_value = m_an_read[0](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[1](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[2](0) & 0x3ff; + m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; + break; + case 0x03: // AN0 -> AN1 -> AN2 -> AN3 + ad_value = m_an_read[0](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[1](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[2](0) & 0x3ff; + m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[3](0) & 0x3ff; + m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; + break; + case 0x04: // AN4 + ad_value = m_an_read[4](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + break; + case 0x05: // AN4 -> AN5 + ad_value = m_an_read[4](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[5](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + break; + case 0x06: // AN4 -> AN5 -> AN6 + ad_value = m_an_read[4](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[5](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[6](0) & 0x3ff; + m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; + break; + case 0x07: // AN4 -> AN5 -> AN6 -> AN7 + ad_value = m_an_read[4](0) & 0x3ff; + m_reg[TMP95C063_ADREG04L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG04H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[5](0) & 0x3ff; + m_reg[TMP95C063_ADREG15L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG15H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[6](0) & 0x3ff; + m_reg[TMP95C063_ADREG26L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG26H] = (ad_value >> 2) & 0xff; + ad_value = m_an_read[7](0) & 0x3ff; + m_reg[TMP95C063_ADREG37L] = (ad_value & 0x3) << 6; + m_reg[TMP95C063_ADREG37H] = (ad_value >> 2) & 0xff; + break; + } + } + + /* Clear BUSY flag, set END flag */ + m_reg[TMP95C063_ADMOD1] &= ~ 0x40; + m_reg[TMP95C063_ADMOD1] |= 0x80; + + m_reg[TMP95C063_INTE0AD] |= 0x80; + m_check_irqs = 1; + } + } +} + + +void tmp95c063_device::device_start() +{ + tlcs900h_device::device_start(); + + m_port1_read.resolve_safe(0); + m_port1_write.resolve_safe(); + m_port2_write.resolve_safe(); + m_port5_read.resolve_safe(0); + m_port5_write.resolve_safe(); + m_port6_read.resolve_safe(0); + m_port6_write.resolve_safe(); + m_port7_read.resolve_safe(0); + m_port7_write.resolve_safe(); + m_port8_read.resolve_safe(0); + m_port8_write.resolve_safe(); + m_port9_read.resolve_safe(0); + m_port9_write.resolve_safe(); + m_porta_read.resolve_safe(0); + m_porta_write.resolve_safe(); + m_portb_read.resolve_safe(0); + m_portb_write.resolve_safe(); + m_portc_read.resolve_safe(0); + m_portd_read.resolve_safe(0); + m_portd_write.resolve_safe(); + m_porte_read.resolve_safe(0); + m_porte_write.resolve_safe(); + m_an_read.resolve_all_safe(0); +} + +void tmp95c063_device::device_reset() +{ + m_pc.b.l = RDMEM( 0xFFFF00 ); + m_pc.b.h = RDMEM( 0xFFFF01 ); + m_pc.b.h2 = RDMEM( 0xFFFF02 ); + m_pc.b.h3 = 0; + /* system mode, iff set to 111, max mode, register bank 0 */ + m_sr.d = 0xF800; + m_regbank = 0; + m_xssp.d = 0x0100; + m_halted = 0; + m_check_irqs = 0; + m_ad_cycles_left = 0; + m_nmi_state = CLEAR_LINE; + m_timer_pre = 0; + m_timer_change[0] = 0; + m_timer_change[1] = 0; + m_timer_change[2] = 0; + m_timer_change[3] = 0; + + m_reg[TMP95C063_P1] = 0x00; + m_reg[TMP95C063_P1CR] = 0x00; + m_reg[TMP95C063_P2] = 0xff; + m_reg[TMP95C063_P2FC] = 0x00; + m_reg[TMP95C063_P5] = 0x3d; + m_reg[TMP95C063_P5CR] = 0x00; + m_reg[TMP95C063_P5FC] = 0x00; + m_reg[TMP95C063_P6] = 0x3b; + m_reg[TMP95C063_P6FC] = 0x00; + m_reg[TMP95C063_P7] = 0xff; + m_reg[TMP95C063_P7CR] = 0x00; + m_reg[TMP95C063_P7FC] = 0x00; + m_reg[TMP95C063_P8] = 0x3f; + m_reg[TMP95C063_P8CR] = 0x00; + m_reg[TMP95C063_P8FC] = 0x00; + m_reg[TMP95C063_PA] = 0x0f; + m_reg[TMP95C063_PACR] = 0x00; + m_reg[TMP95C063_PAFC] = 0x00; + m_reg[TMP95C063_PB] = 0xff; + m_reg[TMP95C063_PBCR] = 0x00; + m_reg[TMP95C063_PBFC] = 0x00; + m_reg[TMP95C063_MSAR0] = 0xff; + m_reg[TMP95C063_MSAR1] = 0xff; + m_reg[TMP95C063_MSAR2] = 0xff; + m_reg[TMP95C063_MSAR3] = 0xff; + m_reg[TMP95C063_MAMR0] = 0xff; + m_reg[TMP95C063_MAMR1] = 0xff; + m_reg[TMP95C063_MAMR2] = 0xff; + m_reg[TMP95C063_MAMR3] = 0xff; + m_reg[TMP95C063_DREFCR1] = 0x00; + m_reg[TMP95C063_DMEMCR1] = 0x80; + m_reg[TMP95C063_DREFCR3] = 0x00; + m_reg[TMP95C063_DMEMCR3] = 0x80; + m_reg[TMP95C063_T01MOD] = 0x00; + m_reg[TMP95C063_T23MOD] = 0x00; + m_reg[TMP95C063_T02FFCR] = 0x00; + m_reg[TMP95C063_T46FFCR] = 0x00; + m_reg[TMP95C063_T8RUN] = 0x00; + m_reg[TMP95C063_TRDC] = 0x00; + m_reg[TMP95C063_T45MOD] = 0x20; + m_reg[TMP95C063_T46FFCR] = 0x00; + m_reg[TMP95C063_PG01CR] = 0x00; + m_reg[TMP95C063_PG0REG] = 0x00; + m_reg[TMP95C063_PG1REG] = 0x00; + m_reg[TMP95C063_SC0MOD] = 0x00; + m_reg[TMP95C063_SC0CR] = 0x00; + m_reg[TMP95C063_BR0CR] = 0x00; + m_reg[TMP95C063_SC1MOD] = 0x00; + m_reg[TMP95C063_SC1CR] = 0x00; + m_reg[TMP95C063_BR1CR] = 0x00; + m_reg[TMP95C063_P8FC] = 0x00; + m_reg[TMP95C063_ODE] = 0x00; + m_reg[TMP95C063_ADMOD1] = 0x00; + m_reg[TMP95C063_ADMOD2] = 0x00; + m_reg[TMP95C063_ADREG04L] = 0x3f; + m_reg[TMP95C063_ADREG04H] = 0x00; + m_reg[TMP95C063_ADREG15L] = 0x3f; + m_reg[TMP95C063_ADREG15H] = 0x00; + m_reg[TMP95C063_ADREG26L] = 0x3f; + m_reg[TMP95C063_ADREG26H] = 0x00; + m_reg[TMP95C063_ADREG37L] = 0x3f; + m_reg[TMP95C063_ADREG37H] = 0x00; + m_reg[TMP95C063_WDMOD] = 0x80; + + for (int i = 0; i < TLCS900_NUM_INPUTS; i++) + m_level[i] = CLEAR_LINE; + + m_prefetch_clear = true; +} + + +uint8_t tmp95c063_device::internal_r(offs_t offset) +{ + switch (offset) + { + case TMP95C063_P1: m_reg[offset] = m_port1_read(0); break; + case TMP95C063_P5: m_reg[offset] = m_port5_read(0); break; + case TMP95C063_P6: m_reg[offset] = m_port6_read(0); break; + case TMP95C063_P7: m_reg[offset] = m_port7_read(0); break; + case TMP95C063_P8: m_reg[offset] = m_port8_read(0); break; + case TMP95C063_P9: m_reg[offset] = m_port9_read(0); break; + case TMP95C063_PA: m_reg[offset] = m_porta_read(0); break; + case TMP95C063_PB: m_reg[offset] = m_portb_read(0); break; + case TMP95C063_PC: m_reg[offset] = m_portc_read(0); break; + case TMP95C063_PD: m_reg[offset] = m_portd_read(0); break; + case TMP95C063_PE: m_reg[offset] = m_porte_read(0); break; + } + return m_reg[ offset ]; +} + + +void tmp95c063_device::internal_w(offs_t offset, uint8_t data) +{ + switch ( offset ) + { + case TMP95C063_T8RUN: + if ( ! ( data & 0x01 ) ) + { + m_timer[0] = 0; + m_timer_change[0] = 0; + } + if ( ! ( data & 0x02 ) ) + { + m_timer[1] = 0; + m_timer_change[1] = 0; + } + if ( ! ( data & 0x04 ) ) + { + m_timer[2] = 0; + m_timer_change[2] = 0; + } + if ( ! ( data & 0x08 ) ) + { + m_timer[3] = 0; + m_timer_change[3] = 0; + } + if ( ! ( data & 0x10 ) ) + m_timer[4] = 0; + if ( ! ( data & 0x20 ) ) + m_timer[5] = 0; + break; + + case TMP95C063_T02FFCR: + switch( data & 0x0c ) + { + case 0x00: + //tlcs900_change_tff( 1, FF_INVERT ); + break; + case 0x04: + //tlcs900_change_tff( 1, FF_SET ); + break; + case 0x08: + //tlcs900_change_tff( 1, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + //tlcs900_change_tff( 3, FF_INVERT ); + break; + case 0x40: + //tlcs900_change_tff( 3, FF_SET ); + break; + case 0x80: + //tlcs900_change_tff( 3, FF_CLEAR ); + break; + } + break; + + case TMP95C063_T46FFCR: + switch( data & 0x0c ) + { + case 0x00: + //tlcs900_change_tff( 5, FF_INVERT ); + break; + case 0x04: + //tlcs900_change_tff( 5, FF_SET ); + break; + case 0x08: + //tlcs900_change_tff( 5, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + //tlcs900_change_tff( 7, FF_INVERT ); + break; + case 0x40: + //tlcs900_change_tff( 7, FF_SET ); + break; + case 0x80: + //tlcs900_change_tff( 7, FF_CLEAR ); + break; + } + break; + + case TMP95C063_T8FFCR: + switch( data & 0x03 ) + { + case 0x00: + //tlcs900_change_tff( 8, FF_INVERT ); + break; + case 0x01: + //tlcs900_change_tff( 8, FF_SET ); + break; + case 0x02: + //tlcs900_change_tff( 8, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + //tlcs900_change_tff( 9, FF_INVERT ); + break; + case 0x40: + //tlcs900_change_tff( 9, FF_SET ); + break; + case 0x80: + //tlcs900_change_tff( 9, FF_CLEAR ); + break; + } + break; + + case TMP95C063_T9FFCR: + switch( data & 0x03 ) + { + case 0x00: + //tlcs900_change_tff( 0xa, FF_INVERT ); + break; + case 0x01: + //tlcs900_change_tff( 0xa, FF_SET ); + break; + case 0x02: + //tlcs900_change_tff( 0xa, FF_CLEAR ); + break; + } + switch( data & 0xc0 ) + { + case 0x00: + //tlcs900_change_tff( 0xb, FF_INVERT ); + break; + case 0x40: + //tlcs900_change_tff( 0xb, FF_SET ); + break; + case 0x80: + //tlcs900_change_tff( 0xb, FF_CLEAR ); + break; + } + break; + + case TMP95C063_MSAR0: + case TMP95C063_MAMR0: + case TMP95C063_MSAR1: + case TMP95C063_MAMR1: + break; + + case TMP95C063_WDMOD: + case TMP95C063_WDCR: + break; + + case TMP95C063_INTE0AD: + case TMP95C063_INTE12: + case TMP95C063_INTE34: + case TMP95C063_INTE56: + case TMP95C063_INTE78: + case TMP95C063_INTET01: + case TMP95C063_INTET23: + case TMP95C063_INTET45: + case TMP95C063_INTET67: + case TMP95C063_INTET89: + case TMP95C063_INTETAB: + case TMP95C063_INTES0: + case TMP95C063_INTES1: + case TMP95C063_INTETC01: + case TMP95C063_INTETC23: + if ( data & 0x80 ) + data = ( data & 0x7f ) | ( m_reg[offset] & 0x80 ); + if ( data & 0x08 ) + data = ( data & 0xf7 ) | ( m_reg[offset] & 0x08 ); + break; + + case TMP95C063_IIMC: + break; + + case TMP95C063_ADMOD1: + // conversion start + if (data & 0x04) + { + data &= ~0x04; + data |= 0x40; + + switch ((m_reg[TMP95C063_ADMOD2] >> 4) & 3) + { + case 0: m_ad_cycles_left = 160; break; + case 1: m_ad_cycles_left = 320; break; + case 2: m_ad_cycles_left = 640; break; + case 3: m_ad_cycles_left = 1280; break; + } + } + break; + + case TMP95C063_ADMOD2: + break; + + default: + break; + } + + m_check_irqs = 1; + m_reg[ offset ] = data; + + switch (offset) + { + case TMP95C063_P1: m_port1_write(0, data, 0xff); break; + case TMP95C063_P2: m_port2_write(0, data, 0xff); break; + case TMP95C063_P5: m_port5_write(0, data, 0xff); break; + case TMP95C063_P6: m_port6_write(0, data, 0xff); break; + case TMP95C063_P7: m_port7_write(0, data, 0xff); break; + case TMP95C063_P8: m_port8_write(0, data, 0xff); break; + case TMP95C063_P9: m_port9_write(0, data, 0xff); break; + case TMP95C063_PA: m_porta_write(0, data, 0xff); break; + case TMP95C063_PB: m_portb_write(0, data, 0xff); break; + //case TMP95C063_PC: m_portc_write(0, data, 0xff); break; + case TMP95C063_PD: m_portd_write(0, data, 0xff); break; + case TMP95C063_PE: m_porte_write(0, data, 0xff); break; + } +} + + +void tmp95c063_device::execute_set_input(int input, int level) +{ + switch( input ) + { + case INPUT_LINE_NMI: + case TLCS900_NMI: + if ( m_level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_nmi_state = level; + } + m_level[TLCS900_NMI] = level; + break; + + case TLCS900_INTWD: + break; + + case TLCS900_INT0: + /* Is INT0 functionality enabled? */ + if (m_reg[TMP95C063_IIMC] & 0x04) + { + if (m_reg[TMP95C063_IIMC] & 0x02) + { + /* Rising edge detect */ + if (m_level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE) + { + /* Leave HALT state */ + m_halted = 0; + m_reg[TMP95C063_INTE0AD] |= 0x08; + } + } + else + { + /* Level detect */ + if (level == ASSERT_LINE) + m_reg[TMP95C063_INTE0AD] |= 0x08; + else + m_reg[TMP95C063_INTE0AD] &= ~ 0x08; + } + } + m_level[TLCS900_INT0] = level; + break; + + case TLCS900_INT1: + if (m_level[TLCS900_INT1] == CLEAR_LINE && level == ASSERT_LINE) + { + m_reg[TMP95C063_INTE12] |= 0x08; + } + else if (m_level[TLCS900_INT1] == ASSERT_LINE && level == CLEAR_LINE) + { + m_reg[TMP95C063_INTE12] &= ~0x08; + } + m_level[TLCS900_INT1] = level; + break; + + case TLCS900_INT2: + if (m_level[TLCS900_INT2] == CLEAR_LINE && level == ASSERT_LINE) + { + m_reg[TMP95C063_INTE12] |= 0x80; + } + else if (m_level[TLCS900_INT2] == ASSERT_LINE && level == CLEAR_LINE) + { + m_reg[TMP95C063_INTE12] &= ~0x80; + } + m_level[TLCS900_INT2] = level; + break; + + case TLCS900_INT3: + if (m_level[TLCS900_INT3] == CLEAR_LINE && level == ASSERT_LINE) + { + m_reg[TMP95C063_INTE34] |= 0x08; + } + else if (m_level[TLCS900_INT3] == ASSERT_LINE && level == CLEAR_LINE) + { + m_reg[TMP95C063_INTE34] &= ~0x08; + } + m_level[TLCS900_INT3] = level; + break; + + case TLCS900_INT4: + if ( ! ( m_reg[TMP95C063_PBCR] & 0x01 ) ) + { + if ( m_level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_reg[TMP95C063_INTE34] |= 0x80; + } + } + m_level[TLCS900_INT4] = level; + break; + + case TLCS900_INT5: + if ( ! ( m_reg[TMP95C063_PBCR] & 0x02 ) ) + { + if ( m_level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_reg[TMP95C063_INTE56] |= 0x08; + } + } + m_level[TLCS900_INT5] = level; + break; + + case TLCS900_INT6: + if (m_level[TLCS900_INT6] == CLEAR_LINE && level == ASSERT_LINE) + { + m_reg[TMP95C063_INTE56] |= 0x80; + } + else if (m_level[TLCS900_INT6] == ASSERT_LINE && level == CLEAR_LINE) + { + m_reg[TMP95C063_INTE56] &= ~0x80; + } + m_level[TLCS900_INT6] = level; + break; + + case TLCS900_TIO: /* External timer input for timer 0 */ + if ( ( m_reg[TMP95C063_T8RUN] & 0x01 ) && ( m_reg[TMP95C063_T01MOD] & 0x03 ) == 0x00 ) + { + if ( m_level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE ) + { + m_timer_change[0] += 1; + } + } + m_level[TLCS900_TIO] = level; + break; + } + m_check_irqs = 1; +} diff --git a/src/devices/cpu/tlcs900/tmp95c063.h b/src/devices/cpu/tlcs900/tmp95c063.h new file mode 100644 index 00000000000..d331a837767 --- /dev/null +++ b/src/devices/cpu/tlcs900/tmp95c063.h @@ -0,0 +1,112 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol + +#ifndef MAME_CPU_TLCS900_TMP95C063_H +#define MAME_CPU_TLCS900_TMP95C063_H + +#pragma once + +#include "tlcs900.h" + +DECLARE_DEVICE_TYPE(TMP95C063, tmp95c063_device) + + +class tmp95c063_device : public tlcs900h_device +{ +public: + // construction/destruction + tmp95c063_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // configuration helpers + auto port1_read() { return m_port1_read.bind(); } + auto port1_write() { return m_port1_write.bind(); } + auto port2_write() { return m_port2_write.bind(); } + auto port5_read() { return m_port5_read.bind(); } + auto port5_write() { return m_port5_write.bind(); } + auto port6_read() { return m_port6_read.bind(); } + auto port6_write() { return m_port6_write.bind(); } + auto port7_read() { return m_port7_read.bind(); } + auto port7_write() { return m_port7_write.bind(); } + auto port8_read() { return m_port8_read.bind(); } + auto port8_write() { return m_port8_write.bind(); } + auto port9_read() { return m_port9_read.bind(); } + auto port9_write() { return m_port9_write.bind(); } + auto porta_read() { return m_porta_read.bind(); } + auto porta_write() { return m_porta_write.bind(); } + auto portb_read() { return m_portb_read.bind(); } + auto portb_write() { return m_portb_write.bind(); } + auto portc_read() { return m_portc_read.bind(); } + auto portd_read() { return m_portd_read.bind(); } + auto portd_write() { return m_portd_write.bind(); } + auto porte_read() { return m_porte_read.bind(); } + auto porte_write() { return m_porte_write.bind(); } + template auto an_read() { return m_an_read[Bit].bind(); } + +protected: + virtual void device_config_complete() override; + virtual void device_start() override; + virtual void device_reset() override; + + virtual void execute_set_input(int inputnum, int state) override; + virtual void tlcs900_check_hdma() override; + virtual void tlcs900_check_irqs() override; + virtual void tlcs900_handle_ad() override; + virtual void tlcs900_handle_timers() override; + +private: + uint8_t internal_r(offs_t offset); + void internal_w(offs_t offset, uint8_t data); + + void internal_mem(address_map &map); + + // Port 1: 8 bit I/O. Shared with d8-d15 + devcb_read8 m_port1_read; + devcb_write8 m_port1_write; + + // Port 2: 8 bit output only. Shared with a16-a23 + devcb_write8 m_port2_write; + + // Port 5: 6 bit I/O + devcb_read8 m_port5_read; + devcb_write8 m_port5_write; + + // Port 6: 8 bit I/O. Shared with cs1, cs3 & dram control + devcb_read8 m_port6_read; + devcb_write8 m_port6_write; + + // Port 7: 8 bit I/O + devcb_read8 m_port7_read; + devcb_write8 m_port7_write; + + // Port 8: 8 bit I/O. Shared with SCOUT, WAIT, NMI2, INT0-INT3 + devcb_read8 m_port8_read; + devcb_write8 m_port8_write; + + // Port 9: 8 bit I/O. Shared with clock input and output for the 8-bit timers + devcb_read8 m_port9_read; + devcb_write8 m_port9_write; + + // Port A: 8 bit I/O. Shared with serial channels 0/1 + devcb_read8 m_porta_read; + devcb_write8 m_porta_write; + + // Port B: 8 bit I/O. Shared with 16bit timers + devcb_read8 m_portb_read; + devcb_write8 m_portb_write; + + // Port C: 8 bit input only. Shared with analogue inputs + devcb_read8 m_portc_read; + + // Port D: 5 bit I/O. Shared with int8_t + devcb_read8 m_portd_read; + devcb_write8 m_portd_write; + + // Port E: 8 bit I/O. + devcb_read8 m_porte_read; + devcb_write8 m_porte_write; + + // analogue inputs, sampled at 10 bits + devcb_read16::array<8> m_an_read; +}; + +#endif // MAME_CPU_TLCS900_TMP95C063_H diff --git a/src/mame/drivers/ngp.cpp b/src/mame/drivers/ngp.cpp index a4713dc199b..37a660be5f3 100644 --- a/src/mame/drivers/ngp.cpp +++ b/src/mame/drivers/ngp.cpp @@ -100,7 +100,7 @@ the Neogeo Pocket. #include "emu.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" -#include "cpu/tlcs900/tlcs900.h" +#include "cpu/tlcs900/tmp95c061.h" #include "cpu/z80/z80.h" #include "sound/t6w28.h" #include "sound/dac.h" diff --git a/src/mame/drivers/taitopjc.cpp b/src/mame/drivers/taitopjc.cpp index 8044e565339..3548eafa97e 100644 --- a/src/mame/drivers/taitopjc.cpp +++ b/src/mame/drivers/taitopjc.cpp @@ -85,7 +85,7 @@ #include "emu.h" #include "cpu/powerpc/ppc.h" -#include "cpu/tlcs900/tlcs900.h" +#include "cpu/tlcs900/tmp95c063.h" #include "cpu/mn10200/mn10200.h" #include "cpu/tms32051/tms32051.h" #include "video/tc0780fpa.h" diff --git a/src/mame/drivers/taitotz.cpp b/src/mame/drivers/taitotz.cpp index 1ebcf69aea0..84840c89d54 100644 --- a/src/mame/drivers/taitotz.cpp +++ b/src/mame/drivers/taitotz.cpp @@ -175,7 +175,7 @@ Notes: #include "bus/ata/ataintf.h" #include "bus/ata/idehd.h" #include "cpu/powerpc/ppc.h" -#include "cpu/tlcs900/tlcs900.h" +#include "cpu/tlcs900/tmp95c063.h" #include "machine/nvram.h" #include "video/poly.h" -- cgit v1.2.3