From cc74ef9ade9c64a59df6bf1eff6a1d0d3ee06e16 Mon Sep 17 00:00:00 2001 From: Wilbert Pol Date: Wed, 25 Dec 2013 12:00:22 +0000 Subject: tx0.c: Modernized cpu core. [Wilbert Pol] Out of whatsnew: Also copied over the support for octal in debugger state from the alto2 branch. --- src/emu/cpu/pdp1/tx0.c | 867 ++++++++++++++++++------------------------------- src/emu/cpu/pdp1/tx0.h | 152 ++++++++- 2 files changed, 455 insertions(+), 564 deletions(-) (limited to 'src/emu/cpu/pdp1') diff --git a/src/emu/cpu/pdp1/tx0.c b/src/emu/cpu/pdp1/tx0.c index de2fc7b8454..459b2b3ee99 100644 --- a/src/emu/cpu/pdp1/tx0.c +++ b/src/emu/cpu/pdp1/tx0.c @@ -15,107 +15,83 @@ #define LOG 0 #define LOG_EXTRA 0 -static void execute_instruction_64kw(device_t *device); -static void execute_instruction_8kw(device_t *device); -static void pulse_reset(device_t *device); +#define READ_TX0_18BIT(A) ((signed)m_program->read_dword((A)<<2)) +#define WRITE_TX0_18BIT(A,V) (m_program->write_dword((A)<<2,(V))) -/* TX-0 Registers */ -struct tx0_state -{ - const tx0_reset_param_t *iface; - - /* processor registers */ - int mbr; /* memory buffer register (18 bits) */ - int ac; /* accumulator (18 bits) */ - int mar; /* memory address register (16 (64kW) or 13 (8kW) bits) */ - int pc; /* program counter (16 (64kW) or 13 (8kW) bits) */ - int ir; /* instruction register (2 (64kW) or 5 (8kW) bits) */ - int lr; /* live register (18 bits) */ - int xr; /* index register (14 bits) (8kW only) */ - int pf; /* program flags (6 bits expandable to 10) (8kW only) */ - - /* operator panel switches */ - int tbr; /* toggle switch buffer register (18 bits) */ - int tac; /* toggle switch accumulator (18 bits) */ - int tss[16]; /* toggle switch storage (18 bits * 16) */ - unsigned int cm_sel : 16; /* individual cm select (1 bit * 16) */ - unsigned int lr_sel : 16; /* individual lr select (1 bit * 16) */ - unsigned int gbl_cm_sel : 1;/* global cm select (1 bit) */ - unsigned int stop_cyc0 : 1; /* stop on cycle 0 */ - unsigned int stop_cyc1 : 1; /* stop on cycle 1 */ - - /* processor state flip-flops */ - unsigned int run : 1; /* processor is running */ - unsigned int rim : 1; /* processor is in read-in mode */ - unsigned int cycle : 2; /* 0 -> fetch */ - /* 1 -> execute (except for taken branches) */ - /* 2 -> extra execute cycle for SXA and ADO */ - unsigned int ioh : 1; /* i-o halt: processor is executing an Input-Output Transfer wait */ - unsigned int ios : 1; /* i-o synchronizer: set on i-o operation completion */ +#define io_handler_rim 3 - /* additional emulator state variables */ - int rim_step; /* current step in rim execution */ +#define PC m_pc +#define IR m_ir +#define MBR m_mbr +#define MAR m_mar +#define AC m_ac +#define LR m_lr +#define XR m_xr +#define PF m_pf - int address_mask; /* address mask */ - int ir_mask; /* IR mask */ +#define ADDRESS_MASK_64KW 0177777 +#define ADDRESS_MASK_8KW 0017777 - int icount; +#define INCREMENT_PC_64KW (PC = (PC+1) & ADDRESS_MASK_64KW) +#define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW) - legacy_cpu_device *device; - address_space *program; -}; -INLINE tx0_state *get_safe_token(device_t *device) +const device_type TX0_8KW = &device_creator; +const device_type TX0_64KW = &device_creator; + + +tx0_device::tx0_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int addr_bits, int address_mask, int ir_mask) + : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) + , m_program_config("program", ENDIANNESS_BIG, 32, addr_bits , -2) + , m_address_mask(address_mask) + , m_ir_mask(ir_mask) + , m_cpy_handler(*this) + , m_r1l_handler(*this) + , m_dis_handler(*this) + , m_r3l_handler(*this) + , m_prt_handler(*this) + , m_rsv_handler(*this) + , m_p6h_handler(*this) + , m_p7h_handler(*this) + , m_sel_handler(*this) + , m_io_reset_callback(*this) { - assert(device != NULL); - assert(device->type() == TX0_64KW || - device->type() == TX0_8KW); - return (tx0_state *)downcast(device)->token(); + m_is_octal = true; } -#define READ_TX0_18BIT(A) ((signed)cpustate->program->read_dword((A)<<2)) -#define WRITE_TX0_18BIT(A,V) (cpustate->program->write_dword((A)<<2,(V))) - - -#define io_handler_rim 3 - -#define PC cpustate->pc -#define IR cpustate->ir -#define MBR cpustate->mbr -#define MAR cpustate->mar -#define AC cpustate->ac -#define LR cpustate->lr -#define XR cpustate->xr -#define PF cpustate->pf +tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : tx0_device(mconfig, TX0_8KW, "TX-0 8KW", tag, owner, clock, "tx0_8w_cpu", __FILE__, 13, ADDRESS_MASK_8KW, 037) +{ +} -#define ADDRESS_MASK_64KW 0177777 -#define ADDRESS_MASK_8KW 0017777 -#define INCREMENT_PC_64KW (PC = (PC+1) & ADDRESS_MASK_64KW) -#define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW) +tx0_64kw_device::tx0_64kw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : tx0_device(mconfig, TX0_64KW, "TX-0 64KW", tag, owner, clock, "tx0_64kw_cpu", __FILE__, 16, ADDRESS_MASK_64KW, 03) +{ +} -static int tx0_read(tx0_state *cpustate, offs_t address) +int tx0_device::tx0_read(offs_t address) { - if ((address >= 16) || (cpustate->gbl_cm_sel) || ((cpustate->cm_sel >> address) & 1)) + if ((address >= 16) || (m_gbl_cm_sel) || ((m_cm_sel >> address) & 1)) /* core memory (CM) */ return READ_TX0_18BIT(address); - else if ((cpustate->lr_sel >> address) & 1) + else if ((m_lr_sel >> address) & 1) /* live register (LR) */ return LR; /* toggle switch storage (TSS) */ - return cpustate->tss[address]; + return m_tss[address]; } -static void tx0_write(tx0_state *cpustate, offs_t address, int data) +void tx0_device::tx0_write(offs_t address, int data) { - if ((address >= 16) || (cpustate->gbl_cm_sel) || ((cpustate->cm_sel >> address) & 1)) + if ((address >= 16) || (m_gbl_cm_sel) || ((m_cm_sel >> address) & 1)) /* core memory (CM) */ WRITE_TX0_18BIT(address, data); - else if ((cpustate->lr_sel >> address) & 1) + else if ((m_lr_sel >> address) & 1) /* live register (LR) */ LR = data; else @@ -124,93 +100,186 @@ static void tx0_write(tx0_state *cpustate, offs_t address, int data) ; } -static void tx0_init_common(legacy_cpu_device *device, device_irq_acknowledge_callback irqcallback, int is_64kw) + +void tx0_device::device_start() { - tx0_state *cpustate = get_safe_token(device); + m_mbr = 0; + m_ac = 0; + m_mar = 0; + m_lr = 0; + m_xr = 0; + m_pf = 0; + m_tbr = 0; + m_tac = 0; + for ( int i = 0; i < 16; i++ ) + { + m_tss[i] = 0; + } + m_cm_sel = 0; + m_lr_sel = 0; + m_gbl_cm_sel = 0; + m_stop_cyc0 = 0; + m_stop_cyc1 = 0; + m_cycle = 0; + + // Resolve callbacks + m_cpy_handler.resolve(); + m_r1l_handler.resolve(); + m_dis_handler.resolve(); + m_r3l_handler.resolve(); + m_prt_handler.resolve(); + m_rsv_handler.resolve(); + m_p6h_handler.resolve(); + m_p7h_handler.resolve(); + m_sel_handler.resolve(); + m_io_reset_callback.resolve(); + + m_program = &space(AS_PROGRAM); + + save_item(NAME(m_mbr)); + save_item(NAME(m_ac)); + save_item(NAME(m_mar)); + save_item(NAME(m_pc)); + save_item(NAME(m_ir)); + save_item(NAME(m_lr)); + save_item(NAME(m_xr)); + save_item(NAME(m_pf)); + save_item(NAME(m_tbr)); + save_item(NAME(m_tac)); + save_item(NAME(m_tss)); + save_item(NAME(m_cm_sel)); + save_item(NAME(m_lr_sel)); + save_item(NAME(m_gbl_cm_sel)); + save_item(NAME(m_stop_cyc0)); + save_item(NAME(m_stop_cyc1)); + save_item(NAME(m_run)); + save_item(NAME(m_rim)); + save_item(NAME(m_cycle)); + save_item(NAME(m_ioh)); + save_item(NAME(m_ios)); + save_item(NAME(m_rim_step)); + + // Register state for debugger + state_add( TX0_PC, "PC", m_pc ).mask(m_address_mask).formatstr("0%06O"); + state_add( TX0_IR, "IR", m_ir ).mask(m_ir_mask) .formatstr("0%02O"); + state_add( TX0_MBR, "MBR", m_mbr ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_MAR, "MAR", m_mar ).mask(m_address_mask).formatstr("0%06O"); + state_add( TX0_AC, "AC", m_ac ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_LR, "LR", m_lr ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_XR, "XR", m_xr ).mask(0037777) .formatstr("0%05O"); + state_add( TX0_PF, "PF", m_pf ).mask(077) .formatstr("0%02O"); + state_add( TX0_TBR, "TBR", m_tbr ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TAC, "TAC", m_tac ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS00, "TSS00", m_tss[000] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS01, "TSS01", m_tss[001] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS02, "TSS02", m_tss[002] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS03, "TSS03", m_tss[003] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS04, "TSS04", m_tss[004] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS05, "TSS05", m_tss[005] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS06, "TSS06", m_tss[006] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS07, "TSS07", m_tss[007] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS10, "TSS10", m_tss[010] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS11, "TSS11", m_tss[011] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS12, "TSS12", m_tss[012] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS13, "TSS13", m_tss[013] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS14, "TSS14", m_tss[014] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS15, "TSS15", m_tss[015] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS16, "TSS16", m_tss[016] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_TSS17, "TSS17", m_tss[017] ).mask(0777777) .formatstr("0%06O"); + state_add( TX0_CM_SEL, "CMSEL", m_cm_sel ).mask(0177777) .formatstr("0%06O"); + state_add( TX0_LR_SEL, "LRSEL", m_lr_sel ).mask(0177777) .formatstr("0%06O"); + state_add( TX0_GBL_CM_SEL, "GBLCMSEL", m_gbl_cm_sel ).mask(1) .formatstr("%1X"); + state_add( TX0_STOP_CYC0, "STOPCYC0", m_stop_cyc0 ).mask(1) .formatstr("%1X"); + state_add( TX0_STOP_CYC1, "STOPCYC1", m_stop_cyc1 ).mask(1) .formatstr("%1X"); + state_add( TX0_RUN, "RUN", m_run ).mask(1) .formatstr("%1X"); + state_add( TX0_RIM, "RIM", m_rim ).mask(1) .formatstr("%1X"); + state_add( TX0_CYCLE, "CYCLE", m_cycle ) .formatstr("%1X"); + state_add( TX0_IOH, "IOH", m_ioh ) .formatstr("%1X"); + state_add( TX0_IOS, "IOS", m_ios ).mask(1) .formatstr("%1X"); + + state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_ir).noshow(); + + m_icountptr = &m_icount; +} - /* clean-up */ - cpustate->iface = (const tx0_reset_param_t *)device->static_config(); - cpustate->address_mask = is_64kw ? ADDRESS_MASK_64KW : ADDRESS_MASK_8KW; - cpustate->ir_mask = is_64kw ? 03 : 037; +void tx0_device::device_reset() +{ + /* reset CPU flip-flops */ + pulse_reset(); - cpustate->device = device; - cpustate->program = &device->space(AS_PROGRAM); + m_gbl_cm_sel = 1; /* HACK */ } -static CPU_INIT( tx0_64kw ) -{ - tx0_init_common(device, irqcallback, 1); -} -static CPU_INIT( tx0_8kw) +void tx0_device::call_io_handler(int io_handler) { - tx0_init_common(device, irqcallback, 0); + /* data will be transferred to AC */ + switch (io_handler) + { + case 0: m_cpy_handler(ASSERT_LINE); break; + case 1: m_r1l_handler(ASSERT_LINE); break; + case 2: m_dis_handler(ASSERT_LINE); break; + case 3: m_r3l_handler(ASSERT_LINE); break; + case 4: m_prt_handler(ASSERT_LINE); break; + case 5: m_rsv_handler(ASSERT_LINE); break; + case 6: m_p6h_handler(ASSERT_LINE); break; + case 7: m_p7h_handler(ASSERT_LINE); break; + } } -static CPU_RESET( tx0 ) -{ - tx0_state *cpustate = get_safe_token(device); - - /* reset CPU flip-flops */ - pulse_reset(device); - - cpustate->gbl_cm_sel = 1; /* HACK */ -} /* execute instructions on this CPU until icount expires */ -static CPU_EXECUTE( tx0_64kw ) +void tx0_64kw_device::execute_run() { - tx0_state *cpustate = get_safe_token(device); - do { - debugger_instruction_hook(device, PC); + debugger_instruction_hook(this, PC); - if (cpustate->ioh && cpustate->ios) + if (m_ioh && m_ios) { - cpustate->ioh = 0; + m_ioh = 0; } - if ((! cpustate->run) && (! cpustate->rim)) - cpustate->icount = 0; /* if processor is stopped, just burn cycles */ - else if (cpustate->rim) + if ((! m_run) && (! m_rim)) + m_icount = 0; /* if processor is stopped, just burn cycles */ + else if (m_rim) { - switch (cpustate->rim_step) + switch (m_rim_step) { case 0: /* read first word as instruction */ AC = 0; - if (cpustate->iface->io_handlers[io_handler_rim]) - (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ - cpustate->rim_step = 1; - cpustate->ios = 0; + call_io_handler(io_handler_rim); + m_rim_step = 1; + m_ios = 0; break; case 1: - if (! cpustate->ios) + if (! m_ios) { /* transfer incomplete: wait some more */ - cpustate->icount = 0; + m_icount = 0; } else { /* data transfer complete */ - cpustate->ios = 0; + m_ios = 0; MBR = AC; IR = MBR >> 16; /* basic opcode */ if ((IR == 2) || (IR == 1)) /* trn or add instruction? */ { PC = MBR & ADDRESS_MASK_64KW; - cpustate->rim = 0; /* exit read-in mode */ - cpustate->run = (IR == 2) ? 1 : 0; /* stop if add instruction */ - cpustate->rim_step = 0; + m_rim = 0; /* exit read-in mode */ + m_run = (IR == 2) ? 1 : 0; /* stop if add instruction */ + m_rim_step = 0; } else if ((IR == 0) || (IR == 3)) /* sto or opr instruction? */ { MAR = MBR & ADDRESS_MASK_64KW; - cpustate->rim_step = 2; + m_rim_step = 2; } } break; @@ -218,106 +287,102 @@ static CPU_EXECUTE( tx0_64kw ) case 2: /* read second word as data */ AC = 0; - if (cpustate->iface->io_handlers[io_handler_rim]) - (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ - cpustate->rim_step = 3; - cpustate->ios = 0; + call_io_handler(io_handler_rim); + m_rim_step = 3; + m_ios = 0; break; case 3: - if (! cpustate->ios) + if (! m_ios) { /* transfer incomplete: wait some more */ - cpustate->icount = 0; + m_icount = 0; } else { /* data transfer complete */ - cpustate->ios = 0; + m_ios = 0; - tx0_write(cpustate, MAR, MBR = AC); + tx0_write(MAR, MBR = AC); - cpustate->rim_step = 0; + m_rim_step = 0; } break; } } else { - if (cpustate->cycle == 0) + if (m_cycle == 0) { /* fetch new instruction */ - MBR = tx0_read(cpustate, MAR = PC); + MBR = tx0_read(MAR = PC); INCREMENT_PC_64KW; IR = MBR >> 16; /* basic opcode */ MAR = MBR & ADDRESS_MASK_64KW; } - if (! cpustate->ioh) + if (! m_ioh) { - if ((cpustate->stop_cyc0 && (cpustate->cycle == 0)) - || (cpustate->stop_cyc1 && (cpustate->cycle == 1))) - cpustate->run = 0; + if ((m_stop_cyc0 && (m_cycle == 0)) + || (m_stop_cyc1 && (m_cycle == 1))) + m_run = 0; - execute_instruction_64kw(device); /* execute instruction */ + execute_instruction_64kw(); } - cpustate->icount --; + m_icount --; } } - while (cpustate->icount > 0); + while (m_icount > 0); } /* execute instructions on this CPU until icount expires */ -static CPU_EXECUTE( tx0_8kw ) +void tx0_8kw_device::execute_run() { - tx0_state *cpustate = get_safe_token(device); - do { - debugger_instruction_hook(device, PC); + debugger_instruction_hook(this, PC); - if (cpustate->ioh && cpustate->ios) + if (m_ioh && m_ios) { - cpustate->ioh = 0; + m_ioh = 0; } - if ((! cpustate->run) && (! cpustate->rim)) - cpustate->icount = 0; /* if processor is stopped, just burn cycles */ - else if (cpustate->rim) + if ((! m_run) && (! m_rim)) + m_icount = 0; /* if processor is stopped, just burn cycles */ + else if (m_rim) { - switch (cpustate->rim_step) + switch (m_rim_step) { case 0: /* read first word as instruction */ AC = 0; - if (cpustate->iface->io_handlers[io_handler_rim]) - (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ - cpustate->rim_step = 1; - cpustate->ios = 0; + call_io_handler(io_handler_rim); + m_rim_step = 1; + m_ios = 0; break; case 1: - if (! cpustate->ios) + if (! m_ios) { /* transfer incomplete: wait some more */ - cpustate->icount = 0; + m_icount = 0; } else { /* data transfer complete */ - cpustate->ios = 0; + m_ios = 0; MBR = AC; IR = MBR >> 13; /* basic opcode */ if ((IR == 16) || (IR == 8)) /* trn or add instruction? */ { PC = MBR & ADDRESS_MASK_8KW; - cpustate->rim = 0; /* exit read-in mode */ - cpustate->run = (IR == 16) ? 1 : 0; /* stop if add instruction */ - cpustate->rim_step = 0; + m_rim = 0; /* exit read-in mode */ + m_run = (IR == 16) ? 1 : 0; /* stop if add instruction */ + m_rim_step = 0; } else if ((IR == 0) || (IR == 24)) /* sto or opr instruction? */ { MAR = MBR & ADDRESS_MASK_8KW; - cpustate->rim_step = 2; + m_rim_step = 2; } } break; @@ -325,370 +390,59 @@ static CPU_EXECUTE( tx0_8kw ) case 2: /* read second word as data */ AC = 0; - if (cpustate->iface->io_handlers[io_handler_rim]) - (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ - cpustate->rim_step = 3; - cpustate->ios = 0; + call_io_handler(io_handler_rim); + m_rim_step = 3; + m_ios = 0; break; case 3: - if (! cpustate->ios) + if (! m_ios) { /* transfer incomplete: wait some more */ - cpustate->icount = 0; + m_icount = 0; } else { /* data transfer complete */ - cpustate->ios = 0; + m_ios = 0; - tx0_write(cpustate, MAR, MBR = AC); + tx0_write(MAR, MBR = AC); - cpustate->rim_step = 0; + m_rim_step = 0; } break; } } else { - if (cpustate->cycle == 0) + if (m_cycle == 0) { /* fetch new instruction */ - MBR = tx0_read(cpustate, MAR = PC); + MBR = tx0_read(MAR = PC); INCREMENT_PC_8KW; IR = MBR >> 13; /* basic opcode */ MAR = MBR & ADDRESS_MASK_8KW; } - if (! cpustate->ioh) + if (! m_ioh) { - if ((cpustate->stop_cyc0 && (cpustate->cycle == 0)) - || (cpustate->stop_cyc1 && (cpustate->cycle == 1))) - cpustate->run = 0; + if ((m_stop_cyc0 && (m_cycle == 0)) + || (m_stop_cyc1 && (m_cycle == 1))) + m_run = 0; - execute_instruction_8kw(device); /* execute instruction */ + execute_instruction_8kw(); } - cpustate->icount -= 1; + m_icount -= 1; } } - while (cpustate->icount > 0); -} - - -static CPU_SET_INFO( tx0 ) -{ - tx0_state *cpustate = get_safe_token(device); - - switch (state) - { - /* --- the following bits of info are set as 64-bit signed integers --- */ - case CPUINFO_INT_SP: (void) info->i; /* no SP */ break; - case CPUINFO_INT_PC: - case CPUINFO_INT_REGISTER + TX0_PC: PC = info->i & cpustate->address_mask; break; - case CPUINFO_INT_REGISTER + TX0_IR: IR = info->i & cpustate->ir_mask; /* weird idea */ break; - case CPUINFO_INT_REGISTER + TX0_MBR: MBR = info->i & 0777777; break; - case CPUINFO_INT_REGISTER + TX0_MAR: MAR = info->i & cpustate->address_mask; break; - case CPUINFO_INT_REGISTER + TX0_AC: AC = info->i & 0777777; break; - case CPUINFO_INT_REGISTER + TX0_LR: LR = info->i & 0777777; break; - case CPUINFO_INT_REGISTER + TX0_XR: XR = info->i & 0037777; break; - case CPUINFO_INT_REGISTER + TX0_PF: PF = info->i & 077; break; - case CPUINFO_INT_REGISTER + TX0_TBR: cpustate->tbr = info->i & 0777777; break; - case CPUINFO_INT_REGISTER + TX0_TAC: cpustate->tac = info->i & 0777777; break; - case CPUINFO_INT_REGISTER + TX0_TSS00: - case CPUINFO_INT_REGISTER + TX0_TSS01: - case CPUINFO_INT_REGISTER + TX0_TSS02: - case CPUINFO_INT_REGISTER + TX0_TSS03: - case CPUINFO_INT_REGISTER + TX0_TSS04: - case CPUINFO_INT_REGISTER + TX0_TSS05: - case CPUINFO_INT_REGISTER + TX0_TSS06: - case CPUINFO_INT_REGISTER + TX0_TSS07: - case CPUINFO_INT_REGISTER + TX0_TSS10: - case CPUINFO_INT_REGISTER + TX0_TSS11: - case CPUINFO_INT_REGISTER + TX0_TSS12: - case CPUINFO_INT_REGISTER + TX0_TSS13: - case CPUINFO_INT_REGISTER + TX0_TSS14: - case CPUINFO_INT_REGISTER + TX0_TSS15: - case CPUINFO_INT_REGISTER + TX0_TSS16: - case CPUINFO_INT_REGISTER + TX0_TSS17: cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)] = info->i & 0777777; break; - case CPUINFO_INT_REGISTER + TX0_CM_SEL: cpustate->cm_sel = info->i & 0177777; break; - case CPUINFO_INT_REGISTER + TX0_LR_SEL: cpustate->lr_sel = info->i & 0177777; break; - case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: cpustate->gbl_cm_sel = info->i ? 1 : 0; break; - case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: cpustate->stop_cyc0 = info->i ? 1 : 0; break; - case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: cpustate->stop_cyc1 = info->i ? 1 : 0; break; - case CPUINFO_INT_REGISTER + TX0_RUN: cpustate->run = info->i ? 1 : 0; break; - case CPUINFO_INT_REGISTER + TX0_RIM: cpustate->rim = info->i ? 1 : 0; break; - case CPUINFO_INT_REGISTER + TX0_CYCLE: if (LOG) logerror("tx0_set_reg to cycle counter ignored\n");/* no way!*/ break; - case CPUINFO_INT_REGISTER + TX0_IOH: if (LOG) logerror("tx0_set_reg to ioh flip-flop ignored\n");/* no way!*/ break; - case CPUINFO_INT_REGISTER + TX0_IOS: cpustate->ios = info->i ? 1 : 0; break; - case CPUINFO_INT_REGISTER + TX0_RESET: pulse_reset(device); break; - case CPUINFO_INT_REGISTER + TX0_IO_COMPLETE:cpustate->ios = 1; break; - } -} - - -CPU_GET_INFO( tx0_64kw ) -{ - tx0_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL; - - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tx0_state); break; - case CPUINFO_INT_INPUT_LINES: info->i = 0; break; - case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; - case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ 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 = 4; break; - case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; - case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; - case CPUINFO_INT_MAX_CYCLES: info->i = 3; break; - - case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; - case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break; - case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break; - case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; - case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; - - case CPUINFO_INT_SP: info->i = 0; /* no SP */ break; - case CPUINFO_INT_PC: info->i = PC; break; - case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break; - - case CPUINFO_INT_REGISTER + TX0_PC: info->i = PC; break; - case CPUINFO_INT_REGISTER + TX0_IR: info->i = IR; break; - case CPUINFO_INT_REGISTER + TX0_MBR: info->i = MBR; break; - case CPUINFO_INT_REGISTER + TX0_MAR: info->i = MAR; break; - case CPUINFO_INT_REGISTER + TX0_AC: info->i = AC; break; - case CPUINFO_INT_REGISTER + TX0_LR: info->i = LR; break; - case CPUINFO_INT_REGISTER + TX0_XR: info->i = XR; break; - case CPUINFO_INT_REGISTER + TX0_PF: info->i = PF; break; - case CPUINFO_INT_REGISTER + TX0_TBR: info->i = cpustate->tbr; break; - case CPUINFO_INT_REGISTER + TX0_TAC: info->i = cpustate->tac; break; - case CPUINFO_INT_REGISTER + TX0_TSS00: - case CPUINFO_INT_REGISTER + TX0_TSS01: - case CPUINFO_INT_REGISTER + TX0_TSS02: - case CPUINFO_INT_REGISTER + TX0_TSS03: - case CPUINFO_INT_REGISTER + TX0_TSS04: - case CPUINFO_INT_REGISTER + TX0_TSS05: - case CPUINFO_INT_REGISTER + TX0_TSS06: - case CPUINFO_INT_REGISTER + TX0_TSS07: - case CPUINFO_INT_REGISTER + TX0_TSS10: - case CPUINFO_INT_REGISTER + TX0_TSS11: - case CPUINFO_INT_REGISTER + TX0_TSS12: - case CPUINFO_INT_REGISTER + TX0_TSS13: - case CPUINFO_INT_REGISTER + TX0_TSS14: - case CPUINFO_INT_REGISTER + TX0_TSS15: - case CPUINFO_INT_REGISTER + TX0_TSS16: - case CPUINFO_INT_REGISTER + TX0_TSS17: info->i = cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)]; break; - case CPUINFO_INT_REGISTER + TX0_CM_SEL: info->i = cpustate->cm_sel; break; - case CPUINFO_INT_REGISTER + TX0_LR_SEL: info->i = cpustate->lr_sel; break; - case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: info->i = cpustate->gbl_cm_sel; break; - case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: info->i = cpustate->stop_cyc0; break; - case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: info->i = cpustate->stop_cyc1; break; - case CPUINFO_INT_REGISTER + TX0_RUN: info->i = cpustate->run; break; - case CPUINFO_INT_REGISTER + TX0_RIM: info->i = cpustate->rim; break; - case CPUINFO_INT_REGISTER + TX0_CYCLE: info->i = cpustate->cycle; break; - case CPUINFO_INT_REGISTER + TX0_IOH: info->i = cpustate->ioh; break; - case CPUINFO_INT_REGISTER + TX0_IOS: info->i = cpustate->ios; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tx0); break; - case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tx0_64kw); break; - case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tx0); break; - case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tx0_64kw); break; - case CPUINFO_FCT_BURN: info->burn = NULL; break; - case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tx0_64kw); break; - case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case CPUINFO_STR_NAME: strcpy(info->s, "TX-0"); break; - case CPUINFO_STR_SHORTNAME: strcpy(info->s, "tx0_64kw_cpu"); break; - case CPUINFO_STR_FAMILY: strcpy(info->s, "TX-0"); break; - case CPUINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case CPUINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break; - - case CPUINFO_STR_FLAGS: strcpy(info->s, ""); break; - - case CPUINFO_STR_REGISTER + TX0_PC: sprintf(info->s, "PC:0%06o", PC); break; - case CPUINFO_STR_REGISTER + TX0_IR: sprintf(info->s, "IR:0%02o", IR); break; - case CPUINFO_STR_REGISTER + TX0_MBR: sprintf(info->s, "MBR:0%06o", MBR); break; - case CPUINFO_STR_REGISTER + TX0_MAR: sprintf(info->s, "MAR:0%06o", MAR); break; - case CPUINFO_STR_REGISTER + TX0_AC: sprintf(info->s, "AC:0%06o", AC); break; - case CPUINFO_STR_REGISTER + TX0_LR: sprintf(info->s, "LR:0%06o", LR); break; - case CPUINFO_STR_REGISTER + TX0_XR: sprintf(info->s, "XR:0%05o", XR); break; - case CPUINFO_STR_REGISTER + TX0_PF: sprintf(info->s, "PF:0%02o", PF); break; - case CPUINFO_STR_REGISTER + TX0_TBR: sprintf(info->s, "TBR:0%06o", cpustate->tbr); break; - case CPUINFO_STR_REGISTER + TX0_TAC: sprintf(info->s, "TAC:0%06o", cpustate->tac); break; - case CPUINFO_STR_REGISTER + TX0_TSS00: - case CPUINFO_STR_REGISTER + TX0_TSS01: - case CPUINFO_STR_REGISTER + TX0_TSS02: - case CPUINFO_STR_REGISTER + TX0_TSS03: - case CPUINFO_STR_REGISTER + TX0_TSS04: - case CPUINFO_STR_REGISTER + TX0_TSS05: - case CPUINFO_STR_REGISTER + TX0_TSS06: - case CPUINFO_STR_REGISTER + TX0_TSS07: - case CPUINFO_STR_REGISTER + TX0_TSS10: - case CPUINFO_STR_REGISTER + TX0_TSS11: - case CPUINFO_STR_REGISTER + TX0_TSS12: - case CPUINFO_STR_REGISTER + TX0_TSS13: - case CPUINFO_STR_REGISTER + TX0_TSS14: - case CPUINFO_STR_REGISTER + TX0_TSS15: - case CPUINFO_STR_REGISTER + TX0_TSS16: - case CPUINFO_STR_REGISTER + TX0_TSS17: sprintf(info->s, "TSS%02o:0%06o", state-(CPUINFO_STR_REGISTER + TX0_TSS00), cpustate->tss[state-(CPUINFO_STR_REGISTER + TX0_TSS00)]); break; - case CPUINFO_STR_REGISTER + TX0_CM_SEL: sprintf(info->s, "CMSEL:0%06o", cpustate->cm_sel); break; - case CPUINFO_STR_REGISTER + TX0_LR_SEL: sprintf(info->s, "LRSEL:0%06o", cpustate->lr_sel); break; - case CPUINFO_STR_REGISTER + TX0_GBL_CM_SEL: sprintf(info->s, "GBLCMSEL:%X", cpustate->gbl_cm_sel); break; - case CPUINFO_STR_REGISTER + TX0_STOP_CYC0: sprintf(info->s, "STOPCYC0:%X", cpustate->stop_cyc0); break; - case CPUINFO_STR_REGISTER + TX0_STOP_CYC1: sprintf(info->s, "STOPCYC1:%X", cpustate->stop_cyc1); break; - case CPUINFO_STR_REGISTER + TX0_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break; - case CPUINFO_STR_REGISTER + TX0_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break; - case CPUINFO_STR_REGISTER + TX0_CYCLE: sprintf(info->s, "CYCLE:%X", cpustate->cycle); break; - case CPUINFO_STR_REGISTER + TX0_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break; - case CPUINFO_STR_REGISTER + TX0_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break; - case CPUINFO_IS_OCTAL: info->i = true; break; - } -} - -CPU_GET_INFO( tx0_8kw ) -{ - tx0_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL; - - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tx0_state); break; - case CPUINFO_INT_INPUT_LINES: info->i = 0; break; - case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; - case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ 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 = 4; break; - case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; - case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; - case CPUINFO_INT_MAX_CYCLES: info->i = 3; break; - - case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; - case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 13; break; - case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break; - case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; - case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; - - case CPUINFO_INT_SP: info->i = 0; /* no SP */ break; - case CPUINFO_INT_PC: info->i = PC; break; - case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break; - - case CPUINFO_INT_REGISTER + TX0_PC: info->i = PC; break; - case CPUINFO_INT_REGISTER + TX0_IR: info->i = IR; break; - case CPUINFO_INT_REGISTER + TX0_MBR: info->i = MBR; break; - case CPUINFO_INT_REGISTER + TX0_MAR: info->i = MAR; break; - case CPUINFO_INT_REGISTER + TX0_AC: info->i = AC; break; - case CPUINFO_INT_REGISTER + TX0_LR: info->i = LR; break; - case CPUINFO_INT_REGISTER + TX0_XR: info->i = XR; break; - case CPUINFO_INT_REGISTER + TX0_PF: info->i = PF; break; - case CPUINFO_INT_REGISTER + TX0_TBR: info->i = cpustate->tbr; break; - case CPUINFO_INT_REGISTER + TX0_TAC: info->i = cpustate->tac; break; - case CPUINFO_INT_REGISTER + TX0_TSS00: - case CPUINFO_INT_REGISTER + TX0_TSS01: - case CPUINFO_INT_REGISTER + TX0_TSS02: - case CPUINFO_INT_REGISTER + TX0_TSS03: - case CPUINFO_INT_REGISTER + TX0_TSS04: - case CPUINFO_INT_REGISTER + TX0_TSS05: - case CPUINFO_INT_REGISTER + TX0_TSS06: - case CPUINFO_INT_REGISTER + TX0_TSS07: - case CPUINFO_INT_REGISTER + TX0_TSS10: - case CPUINFO_INT_REGISTER + TX0_TSS11: - case CPUINFO_INT_REGISTER + TX0_TSS12: - case CPUINFO_INT_REGISTER + TX0_TSS13: - case CPUINFO_INT_REGISTER + TX0_TSS14: - case CPUINFO_INT_REGISTER + TX0_TSS15: - case CPUINFO_INT_REGISTER + TX0_TSS16: - case CPUINFO_INT_REGISTER + TX0_TSS17: info->i = cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)]; break; - case CPUINFO_INT_REGISTER + TX0_CM_SEL: info->i = cpustate->cm_sel; break; - case CPUINFO_INT_REGISTER + TX0_LR_SEL: info->i = cpustate->lr_sel; break; - case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: info->i = cpustate->gbl_cm_sel; break; - case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: info->i = cpustate->stop_cyc0; break; - case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: info->i = cpustate->stop_cyc1; break; - case CPUINFO_INT_REGISTER + TX0_RUN: info->i = cpustate->run; break; - case CPUINFO_INT_REGISTER + TX0_RIM: info->i = cpustate->rim; break; - case CPUINFO_INT_REGISTER + TX0_CYCLE: info->i = cpustate->cycle; break; - case CPUINFO_INT_REGISTER + TX0_IOH: info->i = cpustate->ioh; break; - case CPUINFO_INT_REGISTER + TX0_IOS: info->i = cpustate->ios; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tx0); break; - case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tx0_8kw); break; - case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tx0); break; - case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tx0_8kw); break; - case CPUINFO_FCT_BURN: info->burn = NULL; break; - case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tx0_8kw); break; - case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case CPUINFO_STR_NAME: strcpy(info->s, "TX-0"); break; - case CPUINFO_STR_SHORTNAME: strcpy(info->s, "tx0_8kw_cpu"); break; - case CPUINFO_STR_FAMILY: strcpy(info->s, "TX-0"); break; - case CPUINFO_STR_VERSION: strcpy(info->s, "1.0"); break; - case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; - case CPUINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break; - - case CPUINFO_STR_FLAGS: strcpy(info->s, ""); break; - - case CPUINFO_STR_REGISTER + TX0_PC: sprintf(info->s, "PC:0%06o", PC); break; - case CPUINFO_STR_REGISTER + TX0_IR: sprintf(info->s, "IR:0%02o", IR); break; - case CPUINFO_STR_REGISTER + TX0_MBR: sprintf(info->s, "MBR:0%06o", MBR); break; - case CPUINFO_STR_REGISTER + TX0_MAR: sprintf(info->s, "MAR:0%06o", MAR); break; - case CPUINFO_STR_REGISTER + TX0_AC: sprintf(info->s, "AC:0%06o", AC); break; - case CPUINFO_STR_REGISTER + TX0_LR: sprintf(info->s, "LR:0%06o", LR); break; - case CPUINFO_STR_REGISTER + TX0_XR: sprintf(info->s, "XR:0%05o", XR); break; - case CPUINFO_STR_REGISTER + TX0_PF: sprintf(info->s, "PF:0%02o", PF); break; - case CPUINFO_STR_REGISTER + TX0_TBR: sprintf(info->s, "TBR:0%06o", cpustate->tbr); break; - case CPUINFO_STR_REGISTER + TX0_TAC: sprintf(info->s, "TAC:0%06o", cpustate->tac); break; - case CPUINFO_STR_REGISTER + TX0_TSS00: - case CPUINFO_STR_REGISTER + TX0_TSS01: - case CPUINFO_STR_REGISTER + TX0_TSS02: - case CPUINFO_STR_REGISTER + TX0_TSS03: - case CPUINFO_STR_REGISTER + TX0_TSS04: - case CPUINFO_STR_REGISTER + TX0_TSS05: - case CPUINFO_STR_REGISTER + TX0_TSS06: - case CPUINFO_STR_REGISTER + TX0_TSS07: - case CPUINFO_STR_REGISTER + TX0_TSS10: - case CPUINFO_STR_REGISTER + TX0_TSS11: - case CPUINFO_STR_REGISTER + TX0_TSS12: - case CPUINFO_STR_REGISTER + TX0_TSS13: - case CPUINFO_STR_REGISTER + TX0_TSS14: - case CPUINFO_STR_REGISTER + TX0_TSS15: - case CPUINFO_STR_REGISTER + TX0_TSS16: - case CPUINFO_STR_REGISTER + TX0_TSS17: sprintf(info->s, "TSS%02o:0%06o", state-(CPUINFO_STR_REGISTER + TX0_TSS00), cpustate->tss[state-(CPUINFO_STR_REGISTER + TX0_TSS00)]); break; - case CPUINFO_STR_REGISTER + TX0_CM_SEL: sprintf(info->s, "CMSEL:0%06o", cpustate->cm_sel); break; - case CPUINFO_STR_REGISTER + TX0_LR_SEL: sprintf(info->s, "LRSEL:0%06o", cpustate->lr_sel); break; - case CPUINFO_STR_REGISTER + TX0_GBL_CM_SEL: sprintf(info->s, "GBLCMSEL:%X", cpustate->gbl_cm_sel); break; - case CPUINFO_STR_REGISTER + TX0_STOP_CYC0: sprintf(info->s, "STOPCYC0:%X", cpustate->stop_cyc0); break; - case CPUINFO_STR_REGISTER + TX0_STOP_CYC1: sprintf(info->s, "STOPCYC1:%X", cpustate->stop_cyc1); break; - case CPUINFO_STR_REGISTER + TX0_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break; - case CPUINFO_STR_REGISTER + TX0_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break; - case CPUINFO_STR_REGISTER + TX0_CYCLE: sprintf(info->s, "CYCLE:%X", cpustate->cycle); break; - case CPUINFO_STR_REGISTER + TX0_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break; - case CPUINFO_STR_REGISTER + TX0_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break; - case CPUINFO_IS_OCTAL: info->i = true; break; - } + while (m_icount > 0); } /* execute one instruction */ -static void execute_instruction_64kw(device_t *device) +void tx0_64kw_device::execute_instruction_64kw() { - tx0_state *cpustate = get_safe_token(device); - - if (! cpustate->cycle) + if (! m_cycle) { - cpustate->cycle = 1; /* most frequent case */ + m_cycle = 1; /* most frequent case */ switch (IR) { case 0: /* STOre */ @@ -699,7 +453,7 @@ static void execute_instruction_64kw(device_t *device) if (AC & 0400000) { PC = MAR & ADDRESS_MASK_64KW; - cpustate->cycle = 0; /* instruction only takes one cycle if branch + m_cycle = 0; /* instruction only takes one cycle if branch is taken */ } break; @@ -716,7 +470,7 @@ static void execute_instruction_64kw(device_t *device) if (((MAR & 0030000) >> 12) == 1) /* (0.8) IOS In-Out Stop = Stop machine so that an In-Out command (specified by digits 6 7 8 of MAR) may be executed */ - cpustate->ioh = 1; + m_ioh = 1; if (((MAR & 0007000) >> 9) != 0) { @@ -750,24 +504,23 @@ static void execute_instruction_64kw(device_t *device) /* (5 is undefined) */ int index = (MAR & 0007000) >> 9; - if (cpustate->iface->io_handlers[index]) - (*cpustate->iface->io_handlers[index])(device); - cpustate->ioh = 1; + call_io_handler(index); + m_ioh = 1; } break; } } else { - cpustate->cycle = 0; /* always true */ + m_cycle = 0; /* always true */ switch (IR) { case 0: /* STOre */ - tx0_write(cpustate, MAR, (MBR = AC)); + tx0_write(MAR, (MBR = AC)); break; case 1: /* ADD */ - MBR = tx0_read(cpustate, MAR); + MBR = tx0_read(MAR); AC = AC + MBR; AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ @@ -855,14 +608,14 @@ static void execute_instruction_64kw(device_t *device) if (((MAR & 0030000) >> 12) == 3) /* (1.8) Hlt = Halt the computer */ - cpustate->run = 0; + m_run = 0; break; } } } -static void indexed_address_eval(tx0_state *cpustate) +void tx0_device::indexed_address_eval() { MAR = MAR + XR; MAR = (MAR + (MAR >> 14)) & 0037777; /* propagate carry around */ @@ -873,13 +626,11 @@ static void indexed_address_eval(tx0_state *cpustate) } /* execute one instruction */ -static void execute_instruction_8kw(device_t *device) +void tx0_8kw_device::execute_instruction_8kw() { - tx0_state *cpustate = get_safe_token(device); - - if (! cpustate->cycle) + if (! m_cycle) { - cpustate->cycle = 1; /* most frequent case */ + m_cycle = 1; /* most frequent case */ switch (IR) { case 0: /* STOre */ @@ -903,7 +654,7 @@ static void execute_instruction_8kw(device_t *device) if (AC & 0400000) { PC = MAR & 0017777; - cpustate->cycle = 0; /* instruction only takes one cycle if branch + m_cycle = 0; /* instruction only takes one cycle if branch is taken */ } break; @@ -912,7 +663,7 @@ static void execute_instruction_8kw(device_t *device) if ((AC == 0000000) || (AC == 0777777)) { PC = MAR & 0017777; - cpustate->cycle = 0; /* instruction only takes one cycle if branch + m_cycle = 0; /* instruction only takes one cycle if branch is taken */ } break; @@ -920,7 +671,7 @@ static void execute_instruction_8kw(device_t *device) case 18: /* Transfer and Set indeX */ XR = PC; PC = MAR & 0017777; - cpustate->cycle = 0; /* instruction only takes one cycle if branch + m_cycle = 0; /* instruction only takes one cycle if branch is taken */ break; @@ -932,16 +683,16 @@ static void execute_instruction_8kw(device_t *device) else XR--; PC = MAR & 0017777; - cpustate->cycle = 0; /* instruction only takes one cycle if branch + m_cycle = 0; /* instruction only takes one cycle if branch is taken */ } break; case 21: /* TRansfer indeXed */ - indexed_address_eval(cpustate); + indexed_address_eval(); case 20: /* TRAnsfer */ PC = MAR & 0017777; - cpustate->cycle = 0; /* instruction only takes one cycle if branch + m_cycle = 0; /* instruction only takes one cycle if branch is taken */ break; @@ -949,7 +700,7 @@ static void execute_instruction_8kw(device_t *device) /*if (...) { PC = MAR & 0017777; - cpustate->cycle = 0;*/ /* instruction only takes one cycle if branch + m_cycle = 0;*/ /* instruction only takes one cycle if branch is taken */ /*}*/ break; @@ -969,8 +720,7 @@ static void execute_instruction_8kw(device_t *device) AC = 0; /* (IOS???) SEL = SELect */ - if (cpustate->iface->sel_handler) - (*cpustate->iface->sel_handler)(device); + m_sel_handler(ASSERT_LINE); } else { /* Normal operate class instruction */ @@ -1020,9 +770,8 @@ static void execute_instruction_8kw(device_t *device) /* (5 is undefined) */ int index = (MAR & 0007000) >> 9; - if (cpustate->iface->io_handlers[index]) - (*cpustate->iface->io_handlers[index])(device); - cpustate->ioh = 1; + call_io_handler(index); + m_ioh = 1; } if (((IR & 001) == 00) && ((MAR & 010000) == 010000)) @@ -1038,34 +787,34 @@ static void execute_instruction_8kw(device_t *device) } else { - if (((IR != 2) && (IR != 3)) || (cpustate->cycle == 2)) - cpustate->cycle = 0; + if (((IR != 2) && (IR != 3)) || (m_cycle == 2)) + m_cycle = 0; else - cpustate->cycle = 2; /* SXA and ADO have an extra cycle 2 */ + m_cycle = 2; /* SXA and ADO have an extra cycle 2 */ switch (IR) { case 1: /* STore indeXed */ - indexed_address_eval(cpustate); + indexed_address_eval(); case 0: /* STOre */ - tx0_write(cpustate, MAR, (MBR = AC)); + tx0_write(MAR, (MBR = AC)); break; case 2: /* Store indeX in Address */ - if (cpustate->cycle) + if (m_cycle) { /* cycle 1 */ - MBR = tx0_read(cpustate, MAR); + MBR = tx0_read(MAR); MBR = (MBR & 0760000) | (XR & 0017777); } else { /* cycle 2 */ - tx0_write(cpustate, MAR, MBR); + tx0_write(MAR, MBR); } break; case 3: /* ADd One */ - if (cpustate->cycle) + if (m_cycle) { /* cycle 1 */ - AC = tx0_read(cpustate, MAR) + 1; + AC = tx0_read(MAR) + 1; #if 0 AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ @@ -1078,24 +827,24 @@ static void execute_instruction_8kw(device_t *device) } else { /* cycle 2 */ - tx0_write(cpustate, MAR, (MBR = AC)); + tx0_write(MAR, (MBR = AC)); } break; case 5: /* Store Lr indeXed */ - indexed_address_eval(cpustate); + indexed_address_eval(); case 4: /* Store LR */ - tx0_write(cpustate, MAR, (MBR = LR)); + tx0_write(MAR, (MBR = LR)); break; case 6: /* STore Zero */ - tx0_write(cpustate, MAR, (MBR = 0)); + tx0_write(MAR, (MBR = 0)); break; case 9: /* ADd indeXed */ - indexed_address_eval(cpustate); + indexed_address_eval(); case 8: /* ADD */ - MBR = tx0_read(cpustate, MAR); + MBR = tx0_read(MAR); AC = AC + MBR; AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ @@ -1105,12 +854,12 @@ static void execute_instruction_8kw(device_t *device) break; case 10: /* LoaD indeX */ - MBR = tx0_read(cpustate, MAR); + MBR = tx0_read(MAR); XR = (MBR & 0017777) | ((MBR >> 4) & 0020000); break; case 11: /* AUgment indeX */ - MBR = tx0_read(cpustate, MAR); + MBR = tx0_read(MAR); XR = XR + ((MBR & 0017777) | ((MBR >> 4) & 0020000)); XR = (XR + (XR >> 14)) & 0037777; /* propagate carry around */ @@ -1120,15 +869,15 @@ static void execute_instruction_8kw(device_t *device) break; case 13: /* Load Lr indeXed */ - indexed_address_eval(cpustate); + indexed_address_eval(); case 12: /* Load LR */ - LR = MBR = tx0_read(cpustate, MAR); + LR = MBR = tx0_read(MAR); break; case 15: /* Load Ac indeXed */ - indexed_address_eval(cpustate); + indexed_address_eval(); case 14: /* LoaD Ac */ - AC = MBR = tx0_read(cpustate, MAR); + AC = MBR = tx0_read(MAR); break; case 16: /* TRansfer on Negative */ @@ -1163,11 +912,11 @@ static void execute_instruction_8kw(device_t *device) if (((IR & 001) == 00) && ((MAR & 017000) == 001000)) /* (1.1) TAC = transfer TAC into ac (inclusive or) */ - AC |= cpustate->tac; + AC |= m_tac; if (((IR & 001) == 00) && ((MAR & 017000) == 002000)) /* (1.2) TBR = transfer TBR into mbr (inclusive or) */ - MBR |= cpustate->tbr; + MBR |= m_tbr; if (((IR & 001) == 00) && ((MAR & 017000) == 006000)) /* (1.2) RPF = Read Program Flag register into mbr (inclusive or) */ @@ -1263,7 +1012,7 @@ static void execute_instruction_8kw(device_t *device) if (((IR & 001) == 01) && ((MAR & 017000) == 010000)) /* (1.8) HLT = HaLT the computer and sound chime */ - cpustate->run = 0; + m_run = 0; } break; @@ -1279,10 +1028,8 @@ static void execute_instruction_8kw(device_t *device) reset most registers and flip-flops, and initialize a few emulator state variables. */ -static void pulse_reset(device_t *device) +void tx0_device::pulse_reset() { - tx0_state *cpustate = get_safe_token(device); - /* processor registers */ PC = 0; /* ??? */ IR = 0; /* ??? */ @@ -1292,17 +1039,33 @@ static void pulse_reset(device_t *device) /*LR = 0;*/ /* ??? */ /* processor state flip-flops */ - cpustate->run = 0; /* ??? */ - cpustate->rim = 0; /* ??? */ - cpustate->ioh = 0; /* ??? */ - cpustate->ios = 0; /* ??? */ + m_run = 0; /* ??? */ + m_rim = 0; /* ??? */ + m_ioh = 0; /* ??? */ + m_ios = 0; /* ??? */ - cpustate->rim_step = 0; + m_rim_step = 0; /* now, we kindly ask IO devices to reset, too */ - if (cpustate->iface->io_reset_callback) - (*cpustate->iface->io_reset_callback)(device); + m_io_reset_callback(ASSERT_LINE); +} + +void tx0_device::io_complete() +{ + m_ios = 1; +} + + +offs_t tx0_8kw_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + extern CPU_DISASSEMBLE( tx0_8kw ); + return CPU_DISASSEMBLE_NAME(tx0_8kw)(this, buffer, pc, oprom, opram, options); +} + + +offs_t tx0_64kw_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + extern CPU_DISASSEMBLE( tx0_64kw ); + return CPU_DISASSEMBLE_NAME(tx0_64kw)(this, buffer, pc, oprom, opram, options); } -DEFINE_LEGACY_CPU_DEVICE(TX0_64KW, tx0_64kw); -DEFINE_LEGACY_CPU_DEVICE(TX0_8KW, tx0_8kw); diff --git a/src/emu/cpu/pdp1/tx0.h b/src/emu/cpu/pdp1/tx0.h index cea455927f0..7c4b4d65a56 100644 --- a/src/emu/cpu/pdp1/tx0.h +++ b/src/emu/cpu/pdp1/tx0.h @@ -15,14 +15,103 @@ enum TX0_CM_SEL, TX0_LR_SEL, TX0_GBL_CM_SEL, TX0_STOP_CYC0, TX0_STOP_CYC1, TX0_RUN, TX0_RIM, - TX0_CYCLE, TX0_IOH, TX0_IOS, - TX0_RESET, /* hack, do not use directly, use tx0_pulse_reset instead */ - TX0_IO_COMPLETE /* hack, do not use directly, use tx0_pulse_io_complete instead */ + TX0_CYCLE, TX0_IOH, TX0_IOS }; -struct tx0_reset_param_t +#define MCFG_TX0_CONFIG(_cpy_devcb, _r1l_devcb, _dis_devcb, _r3l_devcb, _prt_devcb, _rsv_devcb, _p6h_devcb, _p7h_devcb, _sel_devcb, _res_devcb) \ + tx0_device::set_cpy_cb(*device, DEVCB2_##_cpy_devcb); \ + tx0_device::set_r1l_cb(*device, DEVCB2_##_r1l_devcb); \ + tx0_device::set_dis_cb(*device, DEVCB2_##_dis_devcb); \ + tx0_device::set_r3l_cb(*device, DEVCB2_##_r3l_devcb); \ + tx0_device::set_prt_cb(*device, DEVCB2_##_prt_devcb); \ + tx0_device::set_rsv_cb(*device, DEVCB2_##_rsv_devcb); \ + tx0_device::set_p6h_cb(*device, DEVCB2_##_p6h_devcb); \ + tx0_device::set_p7h_cb(*device, DEVCB2_##_p7h_devcb); \ + tx0_device::set_sel_cb(*device, DEVCB2_##_sel_devcb); \ + tx0_device::set_res_cb(*device, DEVCB2_##_res_devcb); + + +class tx0_device : public cpu_device { +public: + // construction/destruction + tx0_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int addr_bits, int address_mask, int ir_mask); + + // static configuration helpers + template static devcb2_base &set_cpy_cb(device_t &device, _Object object) { return downcast(device).m_cpy_handler.set_callback(object); } + template static devcb2_base &set_r1l_cb(device_t &device, _Object object) { return downcast(device).m_r1l_handler.set_callback(object); } + template static devcb2_base &set_dis_cb(device_t &device, _Object object) { return downcast(device).m_dis_handler.set_callback(object); } + template static devcb2_base &set_r3l_cb(device_t &device, _Object object) { return downcast(device).m_r3l_handler.set_callback(object); } + template static devcb2_base &set_prt_cb(device_t &device, _Object object) { return downcast(device).m_prt_handler.set_callback(object); } + template static devcb2_base &set_rsv_cb(device_t &device, _Object object) { return downcast(device).m_rsv_handler.set_callback(object); } + template static devcb2_base &set_p6h_cb(device_t &device, _Object object) { return downcast(device).m_p6h_handler.set_callback(object); } + template static devcb2_base &set_p7h_cb(device_t &device, _Object object) { return downcast(device).m_p7h_handler.set_callback(object); } + template static devcb2_base &set_sel_cb(device_t &device, _Object object) { return downcast(device).m_sel_handler.set_callback(object); } + template static devcb2_base &set_res_cb(device_t &device, _Object object) { return downcast(device).m_io_reset_callback.set_callback(object); } + + void pulse_reset(); + void io_complete(); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_execute_interface overrides + virtual UINT32 execute_min_cycles() const { return 1; } + virtual UINT32 execute_max_cycles() const { return 3; } + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; } + + // device_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const { return 4; } + virtual UINT32 disasm_max_opcode_bytes() const { return 4; } + +protected: + address_space_config m_program_config; + + /* processor registers */ + int m_mbr; /* memory buffer register (18 bits) */ + int m_ac; /* accumulator (18 bits) */ + int m_mar; /* memory address register (16 (64kW) or 13 (8kW) bits) */ + int m_pc; /* program counter (16 (64kW) or 13 (8kW) bits) */ + int m_ir; /* instruction register (2 (64kW) or 5 (8kW) bits) */ + int m_lr; /* live register (18 bits) */ + int m_xr; /* index register (14 bits) (8kW only) */ + int m_pf; /* program flags (6 bits expandable to 10) (8kW only) */ + + /* operator panel switches */ + int m_tbr; /* toggle switch buffer register (18 bits) */ + int m_tac; /* toggle switch accumulator (18 bits) */ + int m_tss[16]; /* toggle switch storage (18 bits * 16) */ + UINT16 m_cm_sel; /* individual cm select (1 bit * 16) */ + UINT16 m_lr_sel; /* individual lr select (1 bit * 16) */ + unsigned int m_gbl_cm_sel;/* global cm select (1 bit) */ + unsigned int m_stop_cyc0; /* stop on cycle 0 */ + unsigned int m_stop_cyc1; /* stop on cycle 1 */ + + /* processor state flip-flops */ + unsigned int m_run; /* processor is running */ + unsigned int m_rim; /* processor is in read-in mode */ + unsigned int m_cycle; /* 0 -> fetch */ + /* 1 -> execute (except for taken branches) */ + /* 2 -> extra execute cycle for SXA and ADO */ + + unsigned int m_ioh; /* i-o halt: processor is executing an Input-Output Transfer wait */ + unsigned int m_ios; /* i-o synchronizer: set on i-o operation completion */ + + /* additional emulator state variables */ + int m_rim_step; /* current step in rim execution */ + + int m_address_mask; /* address mask */ + int m_ir_mask; /* IR mask */ + + int m_icount; + + address_space *m_program; + /* 8 standard I/O handlers: 0: cpy (8kW only) 1: r1l @@ -32,18 +121,57 @@ struct tx0_reset_param_t 5: reserved (for unimplemented typ instruction?) 6: p6h 7: p7h */ - void (*io_handlers[8])(device_t *device); + devcb2_write_line m_cpy_handler; + devcb2_write_line m_r1l_handler; + devcb2_write_line m_dis_handler; + devcb2_write_line m_r3l_handler; + devcb2_write_line m_prt_handler; + devcb2_write_line m_rsv_handler; + devcb2_write_line m_p6h_handler; + devcb2_write_line m_p7h_handler; /* select instruction handler */ - void (*sel_handler)(device_t *device); + devcb2_write_line m_sel_handler; /* callback called when reset line is pulsed: IO devices should reset */ - void (*io_reset_callback)(device_t *device); + devcb2_write_line m_io_reset_callback; + + int tx0_read(offs_t address); + void tx0_write(offs_t address, int data); + void call_io_handler(int io_handler); + void indexed_address_eval(); +}; + + +class tx0_8kw_device : public tx0_device +{ +public: + // construction/destruction + tx0_8kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); + +protected: + virtual void execute_run(); + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + +private: + void execute_instruction_8kw(); +}; + + +class tx0_64kw_device : public tx0_device +{ +public: + // construction/destruction + tx0_64kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); + +protected: + virtual void execute_run(); + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + +private: + void execute_instruction_64kw(); }; -/* PUBLIC FUNCTIONS */ -DECLARE_LEGACY_CPU_DEVICE(TX0_64KW, tx0_64kw); -DECLARE_LEGACY_CPU_DEVICE(TX0_8KW, tx0_8kw); -CPU_DISASSEMBLE( tx0_64kw ); -CPU_DISASSEMBLE( tx0_8kw ); +extern const device_type TX0_64KW; +extern const device_type TX0_8KW; #endif /* __TX0_H__ */ -- cgit v1.2.3-70-g09d2