summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/tlcs900/tlcs900.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/tlcs900/tlcs900.c')
-rw-r--r--trunk/src/emu/cpu/tlcs900/tlcs900.c1244
1 files changed, 1244 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/tlcs900/tlcs900.c b/trunk/src/emu/cpu/tlcs900/tlcs900.c
new file mode 100644
index 00000000000..81bb0a4be89
--- /dev/null
+++ b/trunk/src/emu/cpu/tlcs900/tlcs900.c
@@ -0,0 +1,1244 @@
+/*******************************************************************
+
+Toshiba TLCS-900/H emulation
+
+This code only supports the 900/H mode which is needed for Neogeo
+Pocket emulation. The 900 and 900/M modes are not supported yet.
+
+
+TODO:
+- review cycle counts
+- implement the remaining internal mcu features
+- add support for 900 and 900/M modes
+
+*******************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tlcs900.h"
+
+typedef struct _tlcs900_state tlcs900_state;
+struct _tlcs900_state
+{
+ const tlcs900_interface *intf;
+
+ devcb_resolved_write8 to1;
+ devcb_resolved_write8 to3;
+
+ /* registers */
+ PAIR xwa[4];
+ PAIR xbc[4];
+ PAIR xde[4];
+ PAIR xhl[4];
+ PAIR xix;
+ PAIR xiy;
+ PAIR xiz;
+ PAIR xssp;
+ PAIR xnsp;
+ PAIR pc;
+ PAIR sr;
+ PAIR f2; /* f' */
+ /* DMA registers */
+ PAIR dmas[4];
+ PAIR dmad[4];
+ PAIR dmac[4];
+ PAIR dmam[4];
+
+ /* Internal timers, irqs, etc */
+ UINT8 reg[0x80];
+ UINT32 timer_pre;
+ UINT8 timer[6];
+ UINT8 tff1;
+ UINT8 tff3;
+ int timer_change[4];
+
+ /* Current state of input levels */
+ int level[TLCS900_NUM_INPUTS];
+ int check_irqs;
+ int ad_cycles_left;
+ int nmi_state;
+
+ /* used during execution */
+ PAIR dummy; /* for illegal register references */
+ UINT8 op;
+ PAIR ea1, ea2;
+ PAIR imm1, imm2;
+ int cycles;
+ UINT8 *p1_reg8, *p2_reg8;
+ UINT16 *p1_reg16, *p2_reg16;
+ UINT32 *p1_reg32, *p2_reg32;
+
+ int halted;
+ int icount;
+ int regbank;
+ device_irq_acknowledge_callback irqcallback;
+ legacy_cpu_device *device;
+ address_space *program;
+};
+
+
+/* Internal register defines */
+#define P1 0x01
+#define P1CR 0x02
+#define P2 0x06
+#define P2FC 0x09
+#define P5 0x0d
+#define P5CR 0x10
+#define P5FC 0x11
+#define P6 0x12
+#define P7 0x13
+#define P6FC 0x15
+#define P7CR 0x16
+#define P7FC 0x17
+#define P8 0x18
+#define P9 0x19
+#define P8CR 0x1a
+#define P8FC 0x1b
+#define PA 0x1e
+#define PB 0x1f
+#define TRUN 0x20
+#define TREG0 0x22
+#define TREG1 0x23
+#define T01MOD 0x24
+#define TFFCR 0x25
+#define TREG2 0x26
+#define TREG3 0x27
+#define T23MOD 0x28
+#define TRDC 0x29
+#define PACR 0x2c
+#define PAFC 0x2d
+#define PBCR 0x2e
+#define PBFC 0x2f
+#define TREG4L 0x30
+#define TREG4H 0x31
+#define TREG5L 0x32
+#define TREG5H 0x33
+#define CAP1L 0x34
+#define CAP1H 0x35
+#define CAP2L 0x36
+#define CAP2H 0x37
+#define T4MOD 0x38
+#define T4FFCR 0x39
+#define T45CR 0x3a
+#define MSAR0 0x3c
+#define MAMR0 0x3d
+#define MSAR1 0x3e
+#define MAMR1 0x3f
+#define TREG6L 0x40
+#define TREG6H 0x41
+#define TREG7L 0x42
+#define TREG7H 0x43
+#define CAP3L 0x44
+#define CAP3H 0x45
+#define CAP4L 0x46
+#define CAP4H 0x47
+#define T5MOD 0x48
+#define T5FFCR 0x49
+#define PG0REG 0x4c
+#define PG1REG 0x4d
+#define PG01CR 0x4e
+#define SC0BUF 0x50
+#define SC0CR 0x51
+#define SC0MOD 0x52
+#define BR0CR 0x53
+#define SC1BUF 0x54
+#define SC1CR 0x55
+#define SC1MOD 0x56
+#define BR1CR 0x57
+#define ODE 0x58
+#define DREFCR 0x5a
+#define DMEMCR 0x5b
+#define MSAR2 0x5c
+#define MAMR2 0x5d
+#define MSAR3 0x5e
+#define MAMR3 0x5f
+#define ADREG0L 0x60
+#define ADREG0H 0x61
+#define ADREG1L 0x62
+#define ADREG1H 0x63
+#define ADREG2L 0x64
+#define ADREG2H 0x65
+#define ADREG3L 0x66
+#define ADREG3H 0x67
+#define B0CS 0x68
+#define B1CS 0x69
+#define B2CS 0x6a
+#define B3CS 0x6b
+#define BEXCS 0x6c
+#define ADMOD 0x6d
+#define WDMOD 0x6e
+#define WDCR 0x6f
+#define INTE0AD 0x70
+#define INTE45 0x71
+#define INTE67 0x72
+#define INTET10 0x73
+#define INTET32 0x74
+#define INTET54 0x75
+#define INTET76 0x76
+#define INTES0 0x77
+#define INTES1 0x78
+#define INTETC10 0x79
+#define INTETC32 0x7a
+#define IIMC 0x7b
+#define DMA0V 0x7c
+#define DMA1V 0x7d
+#define DMA2V 0x7e
+#define DMA3V 0x7f
+
+
+/* Flag defines */
+#define FLAG_CF 0x01
+#define FLAG_NF 0x02
+#define FLAG_VF 0x04
+#define FLAG_HF 0x10
+#define FLAG_ZF 0x40
+#define FLAG_SF 0x80
+
+
+#define RDMEM(addr) cpustate->program->read_byte( addr )
+#define WRMEM(addr,data) cpustate->program->write_byte( addr, data )
+#define RDOP() RDMEM( cpustate->pc.d ); cpustate->pc.d++
+#define RDMEMW(addr) ( RDMEM(addr) | ( RDMEM(addr+1) << 8 ) )
+#define RDMEML(addr) ( RDMEMW(addr) | ( RDMEMW(addr+2) << 16 ) )
+#define WRMEMW(addr,data) { UINT16 dw = data; WRMEM(addr,dw & 0xff); WRMEM(addr+1,(dw >> 8 )); }
+#define WRMEML(addr,data) { UINT32 dl = data; WRMEMW(addr,dl); WRMEMW(addr+2,(dl >> 16)); }
+
+
+INLINE tlcs900_state *get_safe_token( device_t *device )
+{
+ assert( device != NULL );
+ assert( device->type() == TLCS900H );
+
+ return (tlcs900_state *) downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+static CPU_INIT( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token(device);
+
+ cpustate->intf = (const tlcs900_interface *)device->static_config();
+ cpustate->irqcallback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space( AS_PROGRAM );
+
+ cpustate->to1.resolve(cpustate->intf->to1, *device );
+ cpustate->to3.resolve(cpustate->intf->to3, *device );
+
+ device->save_item( NAME(cpustate->xwa) );
+ device->save_item( NAME(cpustate->xbc) );
+ device->save_item( NAME(cpustate->xde) );
+ device->save_item( NAME(cpustate->xhl) );
+ device->save_item( NAME(cpustate->xix) );
+ device->save_item( NAME(cpustate->xiy) );
+ device->save_item( NAME(cpustate->xiz) );
+ device->save_item( NAME(cpustate->xssp) );
+ device->save_item( NAME(cpustate->xnsp) );
+ device->save_item( NAME(cpustate->pc) );
+ device->save_item( NAME(cpustate->sr) );
+ device->save_item( NAME(cpustate->f2) );
+ device->save_item( NAME(cpustate->dmas) );
+ device->save_item( NAME(cpustate->dmad) );
+ device->save_item( NAME(cpustate->dmac) );
+ device->save_item( NAME(cpustate->dmam) );
+ device->save_item( NAME(cpustate->reg) );
+ device->save_item( NAME(cpustate->timer_pre) );
+ device->save_item( NAME(cpustate->timer) );
+ device->save_item( NAME(cpustate->tff1) );
+ device->save_item( NAME(cpustate->tff3) );
+ device->save_item( NAME(cpustate->timer_change) );
+ device->save_item( NAME(cpustate->level) );
+ device->save_item( NAME(cpustate->check_irqs) );
+ device->save_item( NAME(cpustate->ad_cycles_left) );
+ device->save_item( NAME(cpustate->nmi_state) );
+}
+
+
+static CPU_RESET( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token(device);
+ int i;
+
+ cpustate->pc.b.l = RDMEM( 0xFFFF00 );
+ cpustate->pc.b.h = RDMEM( 0xFFFF01 );
+ cpustate->pc.b.h2 = RDMEM( 0xFFFF02 );
+ cpustate->pc.b.h3 = 0;
+ /* system mode, iff set to 111, max mode, register bank 0 */
+ cpustate->sr.d = 0xF800;
+ cpustate->regbank = 0;
+ cpustate->xssp.d = 0x0100;
+ cpustate->halted = 0;
+ cpustate->check_irqs = 0;
+ cpustate->ad_cycles_left = 0;
+ cpustate->nmi_state = CLEAR_LINE;
+ cpustate->timer_pre = 0;
+ cpustate->timer_change[0] = 0;
+ cpustate->timer_change[1] = 0;
+ cpustate->timer_change[2] = 0;
+ cpustate->timer_change[3] = 0;
+
+ cpustate->reg[P1] = 0x00;
+ cpustate->reg[P1CR] = 0x00;
+ cpustate->reg[P2] = 0xff;
+ cpustate->reg[P2FC] = 0x00;
+ cpustate->reg[P5] = 0x3d;
+ cpustate->reg[P5CR] = 0x00;
+ cpustate->reg[P5FC] = 0x00;
+ cpustate->reg[P6] = 0x3b;
+ cpustate->reg[P6FC] = 0x00;
+ cpustate->reg[P7] = 0xff;
+ cpustate->reg[P7CR] = 0x00;
+ cpustate->reg[P7FC] = 0x00;
+ cpustate->reg[P8] = 0x3f;
+ cpustate->reg[P8CR] = 0x00;
+ cpustate->reg[P8FC] = 0x00;
+ cpustate->reg[PA] = 0x0f;
+ cpustate->reg[PACR] = 0x00;
+ cpustate->reg[PAFC] = 0x00;
+ cpustate->reg[PB] = 0xff;
+ cpustate->reg[PBCR] = 0x00;
+ cpustate->reg[PBFC] = 0x00;
+ cpustate->reg[MSAR0] = 0xff;
+ cpustate->reg[MSAR1] = 0xff;
+ cpustate->reg[MSAR2] = 0xff;
+ cpustate->reg[MSAR3] = 0xff;
+ cpustate->reg[MAMR0] = 0xff;
+ cpustate->reg[MAMR1] = 0xff;
+ cpustate->reg[MAMR2] = 0xff;
+ cpustate->reg[MAMR3] = 0xff;
+ cpustate->reg[DREFCR] = 0x00;
+ cpustate->reg[DMEMCR] = 0x80;
+ cpustate->reg[T01MOD] = 0x00;
+ cpustate->reg[T23MOD] = 0x00;
+ cpustate->reg[TFFCR] = 0x00;
+ cpustate->reg[TRUN] = 0x00;
+ cpustate->reg[TRDC] = 0x00;
+ cpustate->reg[T4MOD] = 0x20;
+ cpustate->reg[T4FFCR] = 0x00;
+ cpustate->reg[T5MOD] = 0x20;
+ cpustate->reg[T5FFCR] = 0x00;
+ cpustate->reg[T45CR] = 0x00;
+ cpustate->reg[PG01CR] = 0x00;
+ cpustate->reg[PG0REG] = 0x00;
+ cpustate->reg[PG1REG] = 0x00;
+ cpustate->reg[SC0MOD] = 0x00;
+ cpustate->reg[SC0CR] = 0x00;
+ cpustate->reg[BR0CR] = 0x00;
+ cpustate->reg[SC1MOD] = 0x00;
+ cpustate->reg[SC1CR] = 0x00;
+ cpustate->reg[BR1CR] = 0x00;
+ cpustate->reg[P8FC] = 0x00;
+ cpustate->reg[ODE] = 0x00;
+ cpustate->reg[ADMOD] = 0x00;
+ cpustate->reg[ADREG0L] = 0x3f;
+ cpustate->reg[ADREG1L] = 0x3f;
+ cpustate->reg[ADREG2L] = 0x3f;
+ cpustate->reg[ADREG3L] = 0x3f;
+ cpustate->reg[WDMOD] = 0x80;
+
+ for ( i = 0; i < TLCS900_NUM_INPUTS; i++ )
+ {
+ cpustate->level[i] = CLEAR_LINE;
+ }
+}
+
+
+static CPU_EXIT( tlcs900 )
+{
+}
+
+
+#include "900tbl.c"
+
+
+#define NUM_MASKABLE_IRQS 22
+static const struct {
+ UINT8 reg;
+ UINT8 iff;
+ UINT8 vector;
+} irq_vector_map[NUM_MASKABLE_IRQS] =
+{
+ { INTETC32, 0x80, 0x80 }, /* INTTC3 */
+ { INTETC32, 0x08, 0x7c }, /* INTTC2 */
+ { INTETC10, 0x80, 0x78 }, /* INTTC1 */
+ { INTETC10, 0x08, 0x74 }, /* INTTC0 */
+ { INTE0AD, 0x80, 0x70 }, /* INTAD */
+ { INTES1, 0x80, 0x6c }, /* INTTX1 */
+ { INTES1, 0x08, 0x68 }, /* INTRX1 */
+ { INTES0, 0x80, 0x64 }, /* INTTX0 */
+ { INTES0, 0x08, 0x60 }, /* INTRX0 */
+ { INTET76, 0x80, 0x5c }, /* INTTR7 */
+ { INTET76, 0x08, 0x58 }, /* INTTR6 */
+ { INTET54, 0x80, 0x54 }, /* INTTR5 */
+ { INTET54, 0x08, 0x50 }, /* INTTR4 */
+ { INTET32, 0x80, 0x4c }, /* INTT3 */
+ { INTET32, 0x08, 0x48 }, /* INTT2 */
+ { INTET10, 0x80, 0x44 }, /* INTT1 */
+ { INTET10, 0x08, 0x40 }, /* INTT0 */
+ /* 0x3c - reserved */
+ { INTE67, 0x80, 0x38 }, /* INT7 */
+ { INTE67, 0x08, 0x34 }, /* INT6 */
+ { INTE45, 0x80, 0x30 }, /* INT5 */
+ { INTE45, 0x08, 0x2c }, /* INT4 */
+ { INTE0AD, 0x08, 0x28 } /* INT0 */
+};
+
+
+INLINE int tlcs900_process_hdma( tlcs900_state *cpustate, int channel )
+{
+ UINT8 vector = ( cpustate->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 < NUM_MASKABLE_IRQS && irq_vector_map[irq].vector != vector )
+ irq++;
+
+ /* Check if our interrupt flip-flop is set */
+ if ( irq < NUM_MASKABLE_IRQS && cpustate->reg[irq_vector_map[irq].reg] & irq_vector_map[irq].iff )
+ {
+ switch( cpustate->dmam[channel].b.l & 0x1f )
+ {
+ case 0x00:
+ WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d += 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x01:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d += 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x02:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d += 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x04:
+ WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d -= 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x05:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d -= 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x06:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmad[channel].d -= 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x08:
+ WRMEM( cpustate->dmad[channel].d, RDMEM( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d += 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x09:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d += 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x0a:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d += 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x0c:
+ WRMEM( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d -= 1;
+ cpustate->cycles += 8;
+ break;
+ case 0x0d:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d -= 2;
+ cpustate->cycles += 8;
+ break;
+ case 0x0e:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->dmas[channel].d -= 4;
+ cpustate->cycles += 12;
+ break;
+ case 0x10:
+ WRMEM( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->cycles += 8;
+ break;
+ case 0x11:
+ WRMEMW( cpustate->dmad[channel].d, RDMEMW( cpustate->dmas[channel].d ) );
+ cpustate->cycles += 8;
+ break;
+ case 0x12:
+ WRMEML( cpustate->dmad[channel].d, RDMEML( cpustate->dmas[channel].d ) );
+ cpustate->cycles += 12;
+ break;
+ case 0x14:
+ cpustate->dmas[channel].d += 1;
+ cpustate->cycles += 5;
+ break;
+ }
+
+ cpustate->dmac[channel].w.l -= 1;
+
+ if ( cpustate->dmac[channel].w.l == 0 )
+ {
+ cpustate->reg[0x7c + channel] = 0;
+ switch( channel )
+ {
+ case 0:
+ cpustate->reg[INTETC10] |= 0x08;
+ break;
+ case 1:
+ cpustate->reg[INTETC10] |= 0x80;
+ break;
+ case 2:
+ cpustate->reg[INTETC32] |= 0x08;
+ break;
+ case 3:
+ cpustate->reg[INTETC32] |= 0x80;
+ break;
+ }
+ }
+
+ /* Clear the interrupt flip-flop */
+ cpustate->reg[irq_vector_map[irq].reg] &= ~irq_vector_map[irq].iff;
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+INLINE void tlcs900_check_hdma( tlcs900_state *cpustate )
+{
+ /* HDMA can only be performed if interrupts are allowed */
+ if ( ( cpustate->sr.b.h & 0x70 ) != 0x70 )
+ {
+ if ( ! tlcs900_process_hdma( cpustate, 0 ) )
+ {
+ if ( ! tlcs900_process_hdma( cpustate, 1 ) )
+ {
+ if ( ! tlcs900_process_hdma( cpustate, 2 ) )
+ {
+ tlcs900_process_hdma( cpustate, 3 );
+ }
+ }
+ }
+ }
+}
+
+
+INLINE void tlcs900_check_irqs( tlcs900_state *cpustate )
+{
+ 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 ( cpustate->nmi_state == ASSERT_LINE )
+ {
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
+ cpustate->pc.d = RDMEML( 0xffff00 + 0x20 );
+ cpustate->cycles += 18;
+
+ cpustate->halted = 0;
+
+ cpustate->nmi_state = CLEAR_LINE;
+
+ return;
+ }
+
+ /* Check regular irqs */
+ for( i = 0; i < NUM_MASKABLE_IRQS; i++ )
+ {
+ if ( cpustate->reg[irq_vector_map[i].reg] & irq_vector_map[i].iff )
+ {
+ switch( irq_vector_map[i].iff )
+ {
+ case 0x80:
+ irq_vectors[ ( cpustate->reg[ irq_vector_map[i].reg ] >> 4 ) & 0x07 ] = i;
+ break;
+ case 0x08:
+ irq_vectors[ cpustate->reg[ irq_vector_map[i].reg ] & 0x07 ] = i;
+ break;
+ }
+ }
+ }
+
+ /* Check highest allowed priority irq */
+ for ( i = MAX( 1, ( ( cpustate->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 vector = irq_vector_map[irq].vector;
+
+ cpustate->xssp.d -= 4;
+ WRMEML( cpustate->xssp.d, cpustate->pc.d );
+ cpustate->xssp.d -= 2;
+ WRMEMW( cpustate->xssp.d, cpustate->sr.w.l );
+
+ /* Mask off any lower priority interrupts */
+ cpustate->sr.b.h = ( cpustate->sr.b.h & 0x8f ) | ( level << 4 );
+
+ cpustate->pc.d = RDMEML( 0xffff00 + vector );
+ cpustate->cycles += 18;
+
+ cpustate->halted = 0;
+
+ /* Clear taken IRQ */
+ cpustate->reg[ irq_vector_map[irq].reg ] &= ~ irq_vector_map[irq].iff;
+ }
+}
+
+
+INLINE void tlcs900_handle_ad( tlcs900_state *cpustate )
+{
+ if ( cpustate->ad_cycles_left > 0 )
+ {
+ cpustate->ad_cycles_left -= cpustate->cycles;
+ if ( cpustate->ad_cycles_left <= 0 )
+ {
+ /* Store A/D converted value */
+ switch( cpustate->reg[ADMOD] & 0x03 )
+ {
+ case 0x00: /* AN0 */
+ cpustate->reg[ADREG0L] |= 0xc0;
+ cpustate->reg[ADREG0H] = 0xff;
+ break;
+ case 0x01: /* AN1 */
+ case 0x02: /* AN2 */
+ case 0x03: /* AN3 */
+ break;
+ }
+
+ /* Clear BUSY flag, set END flag */
+ cpustate->reg[ADMOD] &= ~ 0x40;
+ cpustate->reg[ADMOD] |= 0x80;
+
+ cpustate->reg[INTE0AD] |= 0x80;
+ cpustate->check_irqs = 1;
+ }
+ }
+}
+
+
+enum ff_change
+{
+ FF_CLEAR,
+ FF_SET,
+ FF_INVERT
+};
+
+
+INLINE void tlcs900_change_tff( tlcs900_state *cpustate, int which, int change )
+{
+ switch( which )
+ {
+ case 1:
+ switch( change )
+ {
+ case FF_CLEAR:
+ cpustate->tff1 = 0;
+ break;
+ case FF_SET:
+ cpustate->tff1 = 1;
+ break;
+ case FF_INVERT:
+ cpustate->tff1 ^= 1;
+ break;
+ }
+ if ( !cpustate->to1.isnull() )
+ cpustate->to1(0, cpustate->tff1 );
+ break;
+
+ case 3:
+ switch( change )
+ {
+ case FF_CLEAR:
+ cpustate->tff3 = 0;
+ break;
+ case FF_SET:
+ cpustate->tff3 = 1;
+ break;
+ case FF_INVERT:
+ cpustate->tff3 ^= 1;
+ break;
+ }
+ if ( !cpustate->to3.isnull() )
+ cpustate->to3(0, cpustate->tff3 );
+ break;
+ }
+}
+
+
+INLINE void tlcs900_handle_timers( tlcs900_state *cpustate )
+{
+ UINT32 old_pre = cpustate->timer_pre;
+
+ /* Is the pre-scaler active */
+ if ( cpustate->reg[TRUN] & 0x80 )
+ cpustate->timer_pre += cpustate->cycles;
+
+ /* Timer 0 */
+ if ( cpustate->reg[TRUN] & 0x01 )
+ {
+ switch( cpustate->reg[T01MOD] & 0x03 )
+ {
+ case 0x00: /* TIO */
+ break;
+ case 0x01: /* T1 */
+ cpustate->timer_change[0] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T4 */
+ cpustate->timer_change[0] += ( cpustate->timer_pre >> 9 ) - ( old_pre >> 9 );
+ break;
+ case 0x03: /* T16 */
+ cpustate->timer_change[0] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[0] > 0; cpustate->timer_change[0]-- )
+ {
+//printf("timer0 = %02x, TREG0 = %02x\n", cpustate->timer[0], cpustate->reg[TREG0] );
+ cpustate->timer[0] += 1;
+ if ( cpustate->timer[0] == cpustate->reg[TREG0] )
+ {
+ if ( ( cpustate->reg[T01MOD] & 0x0c ) == 0x00 )
+ {
+ cpustate->timer_change[1] += 1;
+ }
+
+ /* In 16bit timer mode the timer should not be reset */
+ if ( ( cpustate->reg[T01MOD] & 0xc0 ) != 0x40 )
+ {
+ cpustate->timer[0] = 0;
+ cpustate->reg[INTET10] |= 0x08;
+ }
+ }
+ }
+ }
+
+ /* Timer 1 */
+ if ( cpustate->reg[TRUN] & 0x02 )
+ {
+ switch( ( cpustate->reg[T01MOD] >> 2 ) & 0x03 )
+ {
+ case 0x00: /* TO0TRG */
+ break;
+ case 0x01: /* T1 */
+ cpustate->timer_change[1] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T16 */
+ cpustate->timer_change[1] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ case 0x03: /* T256 */
+ cpustate->timer_change[1] += ( cpustate->timer_pre >> 15 ) - ( old_pre >> 15 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[1] > 0; cpustate->timer_change[1]-- )
+ {
+ cpustate->timer[1] += 1;
+ if ( cpustate->timer[1] == cpustate->reg[TREG1] )
+ {
+ cpustate->timer[1] = 0;
+ cpustate->reg[INTET10] |= 0x80;
+
+ if ( cpustate->reg[TFFCR] & 0x02 )
+ {
+ tlcs900_change_tff( cpustate, 1, FF_INVERT );
+ }
+
+ /* In 16bit timer mode also reset timer 0 */
+ if ( ( cpustate->reg[T01MOD] & 0xc0 ) == 0x40 )
+ {
+ cpustate->timer[0] = 0;
+ }
+ }
+ }
+ }
+
+ /* Timer 2 */
+ if ( cpustate->reg[TRUN] & 0x04 )
+ {
+ switch( cpustate->reg[T23MOD] & 0x03 )
+ {
+ case 0x00: /* invalid */
+ case 0x01: /* T1 */
+ cpustate->timer_change[2] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T4 */
+ cpustate->timer_change[2] += ( cpustate->timer_pre >> 9 ) - ( old_pre >> 9 );
+ break;
+ case 0x03: /* T16 */
+ cpustate->timer_change[2] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[2] > 0; cpustate->timer_change[2]-- )
+ {
+ cpustate->timer[2] += 1;
+ if ( cpustate->timer[2] == cpustate->reg[TREG2] )
+ {
+ if ( ( cpustate->reg[T23MOD] & 0x0c ) == 0x00 )
+ {
+ cpustate->timer_change[3] += 1;
+ }
+
+ /* In 16bit timer mode the timer should not be reset */
+ if ( ( cpustate->reg[T23MOD] & 0xc0 ) != 0x40 )
+ {
+ cpustate->timer[2] = 0;
+ cpustate->reg[INTET32] |= 0x08;
+ }
+ }
+ }
+ }
+
+ /* Timer 3 */
+ if ( cpustate->reg[TRUN] & 0x08 )
+ {
+ switch( ( cpustate->reg[T23MOD] >> 2 ) & 0x03 )
+ {
+ case 0x00: /* TO2TRG */
+ break;
+ case 0x01: /* T1 */
+ cpustate->timer_change[3] += ( cpustate->timer_pre >> 7 ) - ( old_pre >> 7 );
+ break;
+ case 0x02: /* T16 */
+ cpustate->timer_change[3] += ( cpustate->timer_pre >> 11 ) - ( old_pre >> 11 );
+ break;
+ case 0x03: /* T256 */
+ cpustate->timer_change[3] += ( cpustate->timer_pre >> 15 ) - ( old_pre >> 15 );
+ break;
+ }
+
+ for( ; cpustate->timer_change[3] > 0; cpustate->timer_change[3]-- )
+ {
+ cpustate->timer[3] += 1;
+ if ( cpustate->timer[3] == cpustate->reg[TREG3] )
+ {
+ cpustate->timer[3] = 0;
+ cpustate->reg[INTET32] |= 0x80;
+
+ if ( cpustate->reg[TFFCR] & 0x20 )
+ {
+ tlcs900_change_tff( cpustate, 3, FF_INVERT );
+ }
+
+ /* In 16bit timer mode also reset timer 2 */
+ if ( ( cpustate->reg[T23MOD] & 0xc0 ) == 0x40 )
+ {
+ cpustate->timer[2] = 0;
+ }
+ }
+ }
+ }
+
+ cpustate->timer_pre &= 0xffffff;
+}
+
+
+static CPU_EXECUTE( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token(device);
+
+ do
+ {
+ const tlcs900inst *inst;
+
+ cpustate->cycles = 0;
+
+ if ( cpustate->check_irqs )
+ {
+ tlcs900_check_irqs( cpustate );
+ cpustate->check_irqs = 0;
+ }
+
+ debugger_instruction_hook( device, cpustate->pc.d );
+
+ if ( cpustate->halted )
+ {
+ cpustate->cycles += 8;
+ }
+ else
+ {
+ cpustate->op = RDOP();
+ inst = &mnemonic[cpustate->op];
+ prepare_operands( cpustate, inst );
+
+ /* Execute the instruction */
+ inst->opfunc( cpustate );
+ cpustate->cycles += inst->cycles;
+ }
+
+ tlcs900_handle_ad( cpustate );
+
+ tlcs900_handle_timers( cpustate );
+
+ tlcs900_check_hdma( cpustate );
+
+ cpustate->icount -= cpustate->cycles;
+ } while ( cpustate->icount > 0 );
+}
+
+
+static void tlcs900_input_level_change( tlcs900_state *cpustate, int input, int level )
+{
+ switch( input )
+ {
+ case INPUT_LINE_NMI:
+ case TLCS900_NMI:
+ if ( cpustate->level[TLCS900_NMI] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->nmi_state = level;
+ }
+ cpustate->level[TLCS900_NMI] = level;
+ break;
+
+ case TLCS900_INTWD:
+ break;
+
+ case TLCS900_INT0:
+ /* Is INT0 functionality enabled? */
+ if ( cpustate->reg[IIMC] & 0x04 )
+ {
+ if ( cpustate->reg[IIMC] & 0x02 )
+ {
+ /* Rising edge detect */
+ if ( cpustate->level[TLCS900_INT0] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ /* Leave HALT state */
+ cpustate->halted = 0;
+ cpustate->reg[INTE0AD] |= 0x08;
+ }
+ }
+ else
+ {
+ /* Level detect */
+ if ( level == ASSERT_LINE )
+ cpustate->reg[INTE0AD] |= 0x08;
+ else
+ cpustate->reg[INTE0AD] &= ~ 0x08;
+ }
+ }
+ cpustate->level[TLCS900_INT0] = level;
+ break;
+
+ case TLCS900_INT4:
+ if ( ! ( cpustate->reg[PBCR] & 0x01 ) )
+ {
+ if ( cpustate->level[TLCS900_INT4] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->reg[INTE45] |= 0x08;
+ }
+ }
+ cpustate->level[TLCS900_INT4] = level;
+ break;
+
+ case TLCS900_INT5:
+ if ( ! ( cpustate->reg[PBCR] & 0x02 ) )
+ {
+ if ( cpustate->level[TLCS900_INT5] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->reg[INTE45] |= 0x80;
+ }
+ }
+ cpustate->level[TLCS900_INT5] = level;
+ break;
+
+ case TLCS900_TIO: /* External timer input for timer 0 */
+ if ( ( cpustate->reg[TRUN] & 0x01 ) && ( cpustate->reg[T01MOD] & 0x03 ) == 0x00 )
+ {
+ if ( cpustate->level[TLCS900_TIO] == CLEAR_LINE && level == ASSERT_LINE )
+ {
+ cpustate->timer_change[0] += 1;
+ }
+ }
+ cpustate->level[TLCS900_TIO] = level;
+ break;
+ }
+ cpustate->check_irqs = 1;
+}
+
+
+static READ8_HANDLER( tlcs900_internal_r )
+{
+ tlcs900_state *cpustate = get_safe_token( &space->device() );
+
+ return cpustate->reg[ offset ];
+}
+
+
+static WRITE8_HANDLER( tlcs900_internal_w )
+{
+ tlcs900_state *cpustate = get_safe_token( &space->device() );
+
+ switch ( offset )
+ {
+ case TRUN:
+ if ( ! ( data & 0x01 ) )
+ {
+ cpustate->timer[0] = 0;
+ cpustate->timer_change[0] = 0;
+ }
+ if ( ! ( data & 0x02 ) )
+ {
+ cpustate->timer[1] = 0;
+ cpustate->timer_change[1] = 0;
+ }
+ if ( ! ( data & 0x04 ) )
+ {
+ cpustate->timer[2] = 0;
+ cpustate->timer_change[2] = 0;
+ }
+ if ( ! ( data & 0x08 ) )
+ {
+ cpustate->timer[3] = 0;
+ cpustate->timer_change[3] = 0;
+ }
+ if ( ! ( data & 0x10 ) )
+ cpustate->timer[4] = 0;
+ if ( ! ( data & 0x20 ) )
+ cpustate->timer[5] = 0;
+ break;
+
+ case TFFCR:
+ switch( data & 0x0c )
+ {
+ case 0x00:
+ tlcs900_change_tff( cpustate, 1, FF_INVERT );
+ break;
+ case 0x04:
+ tlcs900_change_tff( cpustate, 1, FF_SET );
+ break;
+ case 0x08:
+ tlcs900_change_tff( cpustate, 1, FF_CLEAR );
+ break;
+ }
+ switch( data & 0xc0 )
+ {
+ case 0x00:
+ tlcs900_change_tff( cpustate, 3, FF_INVERT );
+ break;
+ case 0x40:
+ tlcs900_change_tff( cpustate, 3, FF_SET );
+ break;
+ case 0x80:
+ tlcs900_change_tff( cpustate, 3, FF_CLEAR );
+ break;
+ }
+ break;
+ case MSAR0:
+ case MAMR0:
+ case MSAR1:
+ case MAMR1:
+ break;
+
+ case ADMOD:
+ /* Preserve read-only bits */
+ data = ( cpustate->reg[ADMOD] & 0xc0 ) | ( data & 0x3f );
+
+ /* Check for A/D request start */
+ if ( data & 0x04 )
+ {
+ data &= ~0x04;
+ data |= 0x40;
+ cpustate->ad_cycles_left = ( data & 0x08 ) ? 640 : 320;
+ }
+ break;
+
+ case WDMOD:
+ case WDCR:
+ break;
+
+ case INTE0AD:
+ case INTE45:
+ case INTE67:
+ case INTET10:
+ case INTET32:
+ case INTET54:
+ case INTET76:
+ case INTES0:
+ case INTES1:
+ case INTETC10:
+ case INTETC32:
+ if ( data & 0x80 )
+ data = ( data & 0x7f ) | ( cpustate->reg[offset] & 0x80 );
+ if ( data & 0x08 )
+ data = ( data & 0xf7 ) | ( cpustate->reg[offset] & 0x08 );
+ break;
+
+ case IIMC:
+ break;
+
+ default:
+ break;
+ }
+
+ cpustate->check_irqs = 1;
+ cpustate->reg[ offset ] = data;
+}
+
+
+static ADDRESS_MAP_START( tlcs900_mem, AS_PROGRAM, 8, legacy_cpu_device )
+ AM_RANGE( 0x000000, 0x00007f ) AM_READWRITE_LEGACY( tlcs900_internal_r, tlcs900_internal_w )
+ADDRESS_MAP_END
+
+
+static CPU_SET_INFO( tlcs900 )
+{
+ tlcs900_state *cpustate = get_safe_token( device );
+
+ switch ( state )
+ {
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_NMI:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INTWD:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT0:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT4:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT5:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_TIO:
+ tlcs900_input_level_change( cpustate, state - CPUINFO_INT_INPUT_STATE, info->i ); break;
+ }
+}
+
+
+CPU_GET_INFO( tlcs900h )
+{
+ tlcs900_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL;
+
+ switch( state )
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tlcs900_state); break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 7; break; /* FIXME */
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; /* FIXME */
+ case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; /* FIXME */
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI:
+ case CPUINFO_INT_INPUT_STATE + TLCS900_NMI: info->i = cpustate->level[TLCS900_NMI]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INTWD: info->i = cpustate->level[TLCS900_INTWD]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT0: info->i = cpustate->level[TLCS900_INT0]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT4: info->i = cpustate->level[TLCS900_INT4]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_INT5: info->i = cpustate->level[TLCS900_INT5]; break;
+ case CPUINFO_INT_INPUT_STATE + TLCS900_TIO: info->i = cpustate->level[TLCS900_TIO]; break;
+
+ case CPUINFO_INT_PC: info->i = cpustate->pc.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_PC: info->i = cpustate->pc.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_SR: info->i = cpustate->sr.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA0: info->i = cpustate->xwa[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC0: info->i = cpustate->xbc[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE0: info->i = cpustate->xde[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL0: info->i = cpustate->xhl[0].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA1: info->i = cpustate->xwa[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC1: info->i = cpustate->xbc[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE1: info->i = cpustate->xde[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL1: info->i = cpustate->xhl[1].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA2: info->i = cpustate->xwa[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC2: info->i = cpustate->xbc[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE2: info->i = cpustate->xde[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL2: info->i = cpustate->xhl[2].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XWA3: info->i = cpustate->xwa[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XBC3: info->i = cpustate->xbc[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XDE3: info->i = cpustate->xde[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XHL3: info->i = cpustate->xhl[3].d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XIX: info->i = cpustate->xix.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XIY: info->i = cpustate->xiy.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XIZ: info->i = cpustate->xiz.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XNSP: info->i = cpustate->xnsp.d; break;
+ case CPUINFO_INT_REGISTER + TLCS900_XSSP: info->i = cpustate->xssp.d; break;
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tlcs900); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tlcs900); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tlcs900); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(tlcs900); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tlcs900); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tlcs900); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME(tlcs900_mem); break;
+
+ case CPUINFO_STR_REGISTER + TLCS900_PC: sprintf( info->s, "PC:%08x", cpustate->pc.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_SR: sprintf( info->s, "SR:%c%d%c%d%c%c%c%c%c%c%c%c",
+ cpustate->sr.w.l & 0x8000 ? 'S' : 'U',
+ ( cpustate->sr.w.l & 0x7000 ) >> 12,
+ cpustate->sr.w.l & 0x0800 ? 'M' : 'N',
+ ( cpustate->sr.w.l & 0x0700 ) >> 8,
+ cpustate->sr.w.l & 0x0080 ? 'S' : '.',
+ cpustate->sr.w.l & 0x0040 ? 'Z' : '.',
+ cpustate->sr.w.l & 0x0020 ? '1' : '.',
+ cpustate->sr.w.l & 0x0010 ? 'H' : '.',
+ cpustate->sr.w.l & 0x0008 ? '1' : '.',
+ cpustate->sr.w.l & 0x0004 ? 'V' : '.',
+ cpustate->sr.w.l & 0x0002 ? 'N' : '.',
+ cpustate->sr.w.l & 0x0001 ? 'C' : '.' );
+ break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA0: sprintf( info->s, "XWA0:%08x", cpustate->xwa[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC0: sprintf( info->s, "XBC0:%08x", cpustate->xbc[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE0: sprintf( info->s, "XDE0:%08x", cpustate->xde[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL0: sprintf( info->s, "XHL0:%08x", cpustate->xhl[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA1: sprintf( info->s, "XWA1:%08x", cpustate->xwa[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC1: sprintf( info->s, "XBC1:%08x", cpustate->xbc[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE1: sprintf( info->s, "XDE1:%08x", cpustate->xde[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL1: sprintf( info->s, "XHL1:%08x", cpustate->xhl[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA2: sprintf( info->s, "XWA2:%08x", cpustate->xwa[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC2: sprintf( info->s, "XBC2:%08x", cpustate->xbc[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE2: sprintf( info->s, "XDE2:%08x", cpustate->xde[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL2: sprintf( info->s, "XHL2:%08x", cpustate->xhl[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XWA3: sprintf( info->s, "XWA3:%08x", cpustate->xwa[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XBC3: sprintf( info->s, "XBC3:%08x", cpustate->xbc[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XDE3: sprintf( info->s, "XDE3:%08x", cpustate->xde[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XHL3: sprintf( info->s, "XHL3:%08x", cpustate->xhl[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XIX: sprintf( info->s, "XIX:%08x", cpustate->xix.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XIY: sprintf( info->s, "XIY:%08x", cpustate->xiy.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XIZ: sprintf( info->s, "XIZ:%08x", cpustate->xiz.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XNSP: sprintf( info->s, "XNSP:%08x", cpustate->xnsp.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_XSSP: sprintf( info->s, "XSSP:%08x", cpustate->xssp.d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS0: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD0: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[0].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC0: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[0].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM0: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[0].b.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS1: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD1: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[1].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC1: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[1].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM1: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[1].b.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS2: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD2: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[2].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC2: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[2].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM2: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[2].b.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAS3: sprintf( info->s, "DMAS0:%08x", cpustate->dmas[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAD3: sprintf( info->s, "DMAD0:%08x", cpustate->dmad[3].d ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAC3: sprintf( info->s, "DMAC0:%04x", cpustate->dmac[3].w.l ); break;
+ case CPUINFO_STR_REGISTER + TLCS900_DMAM3: sprintf( info->s, "DMAM0:%02x", cpustate->dmam[3].b.l ); break;
+
+ case DEVINFO_STR_NAME: strcpy( info->s, "TLCS-900/H" ); break;
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Toshiba TLCS-900" ); break;
+ case DEVINFO_STR_VERSION: strcpy( info->s, "0.1" ); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break;
+ case DEVINFO_STR_CREDITS: strcpy( info->s, "Copyright Wilbert Pol" ); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(TLCS900H, tlcs900h);