trunk/src/emu/cpu/pdp1/tx0.c
| r26748 | r26749 | |
| 15 | 15 | #define LOG 0 |
| 16 | 16 | #define LOG_EXTRA 0 |
| 17 | 17 | |
| 18 | | static void execute_instruction_64kw(device_t *device); |
| 19 | | static void execute_instruction_8kw(device_t *device); |
| 20 | | static void pulse_reset(device_t *device); |
| 21 | 18 | |
| 19 | #define READ_TX0_18BIT(A) ((signed)m_program->read_dword((A)<<2)) |
| 20 | #define WRITE_TX0_18BIT(A,V) (m_program->write_dword((A)<<2,(V))) |
| 22 | 21 | |
| 23 | | /* TX-0 Registers */ |
| 24 | | struct tx0_state |
| 25 | | { |
| 26 | | const tx0_reset_param_t *iface; |
| 27 | 22 | |
| 28 | | /* processor registers */ |
| 29 | | int mbr; /* memory buffer register (18 bits) */ |
| 30 | | int ac; /* accumulator (18 bits) */ |
| 31 | | int mar; /* memory address register (16 (64kW) or 13 (8kW) bits) */ |
| 32 | | int pc; /* program counter (16 (64kW) or 13 (8kW) bits) */ |
| 33 | | int ir; /* instruction register (2 (64kW) or 5 (8kW) bits) */ |
| 34 | | int lr; /* live register (18 bits) */ |
| 35 | | int xr; /* index register (14 bits) (8kW only) */ |
| 36 | | int pf; /* program flags (6 bits expandable to 10) (8kW only) */ |
| 23 | #define io_handler_rim 3 |
| 37 | 24 | |
| 38 | | /* operator panel switches */ |
| 39 | | int tbr; /* toggle switch buffer register (18 bits) */ |
| 40 | | int tac; /* toggle switch accumulator (18 bits) */ |
| 41 | | int tss[16]; /* toggle switch storage (18 bits * 16) */ |
| 42 | | unsigned int cm_sel : 16; /* individual cm select (1 bit * 16) */ |
| 43 | | unsigned int lr_sel : 16; /* individual lr select (1 bit * 16) */ |
| 44 | | unsigned int gbl_cm_sel : 1;/* global cm select (1 bit) */ |
| 45 | | unsigned int stop_cyc0 : 1; /* stop on cycle 0 */ |
| 46 | | unsigned int stop_cyc1 : 1; /* stop on cycle 1 */ |
| 25 | #define PC m_pc |
| 26 | #define IR m_ir |
| 27 | #define MBR m_mbr |
| 28 | #define MAR m_mar |
| 29 | #define AC m_ac |
| 30 | #define LR m_lr |
| 31 | #define XR m_xr |
| 32 | #define PF m_pf |
| 47 | 33 | |
| 48 | | /* processor state flip-flops */ |
| 49 | | unsigned int run : 1; /* processor is running */ |
| 50 | | unsigned int rim : 1; /* processor is in read-in mode */ |
| 51 | | unsigned int cycle : 2; /* 0 -> fetch */ |
| 52 | | /* 1 -> execute (except for taken branches) */ |
| 53 | | /* 2 -> extra execute cycle for SXA and ADO */ |
| 34 | #define ADDRESS_MASK_64KW 0177777 |
| 35 | #define ADDRESS_MASK_8KW 0017777 |
| 54 | 36 | |
| 55 | | unsigned int ioh : 1; /* i-o halt: processor is executing an Input-Output Transfer wait */ |
| 56 | | unsigned int ios : 1; /* i-o synchronizer: set on i-o operation completion */ |
| 37 | #define INCREMENT_PC_64KW (PC = (PC+1) & ADDRESS_MASK_64KW) |
| 38 | #define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW) |
| 57 | 39 | |
| 58 | | /* additional emulator state variables */ |
| 59 | | int rim_step; /* current step in rim execution */ |
| 60 | 40 | |
| 61 | | int address_mask; /* address mask */ |
| 62 | | int ir_mask; /* IR mask */ |
| 41 | const device_type TX0_8KW = &device_creator<tx0_8kw_device>; |
| 42 | const device_type TX0_64KW = &device_creator<tx0_64kw_device>; |
| 63 | 43 | |
| 64 | | int icount; |
| 65 | 44 | |
| 66 | | legacy_cpu_device *device; |
| 67 | | address_space *program; |
| 68 | | }; |
| 45 | 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) |
| 46 | : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) |
| 47 | , m_program_config("program", ENDIANNESS_BIG, 32, addr_bits , -2) |
| 48 | , m_address_mask(address_mask) |
| 49 | , m_ir_mask(ir_mask) |
| 50 | , m_cpy_handler(*this) |
| 51 | , m_r1l_handler(*this) |
| 52 | , m_dis_handler(*this) |
| 53 | , m_r3l_handler(*this) |
| 54 | , m_prt_handler(*this) |
| 55 | , m_rsv_handler(*this) |
| 56 | , m_p6h_handler(*this) |
| 57 | , m_p7h_handler(*this) |
| 58 | , m_sel_handler(*this) |
| 59 | , m_io_reset_callback(*this) |
| 60 | { |
| 61 | m_is_octal = true; |
| 62 | } |
| 69 | 63 | |
| 70 | | INLINE tx0_state *get_safe_token(device_t *device) |
| 64 | tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 65 | : tx0_device(mconfig, TX0_8KW, "TX-0 8KW", tag, owner, clock, "tx0_8w_cpu", __FILE__, 13, ADDRESS_MASK_8KW, 037) |
| 71 | 66 | { |
| 72 | | assert(device != NULL); |
| 73 | | assert(device->type() == TX0_64KW || |
| 74 | | device->type() == TX0_8KW); |
| 75 | | return (tx0_state *)downcast<legacy_cpu_device *>(device)->token(); |
| 76 | 67 | } |
| 77 | 68 | |
| 78 | | #define READ_TX0_18BIT(A) ((signed)cpustate->program->read_dword((A)<<2)) |
| 79 | | #define WRITE_TX0_18BIT(A,V) (cpustate->program->write_dword((A)<<2,(V))) |
| 80 | 69 | |
| 70 | tx0_64kw_device::tx0_64kw_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 71 | : tx0_device(mconfig, TX0_64KW, "TX-0 64KW", tag, owner, clock, "tx0_64kw_cpu", __FILE__, 16, ADDRESS_MASK_64KW, 03) |
| 72 | { |
| 73 | } |
| 81 | 74 | |
| 82 | | #define io_handler_rim 3 |
| 83 | 75 | |
| 84 | | #define PC cpustate->pc |
| 85 | | #define IR cpustate->ir |
| 86 | | #define MBR cpustate->mbr |
| 87 | | #define MAR cpustate->mar |
| 88 | | #define AC cpustate->ac |
| 89 | | #define LR cpustate->lr |
| 90 | | #define XR cpustate->xr |
| 91 | | #define PF cpustate->pf |
| 92 | | |
| 93 | | #define ADDRESS_MASK_64KW 0177777 |
| 94 | | #define ADDRESS_MASK_8KW 0017777 |
| 95 | | |
| 96 | | #define INCREMENT_PC_64KW (PC = (PC+1) & ADDRESS_MASK_64KW) |
| 97 | | #define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW) |
| 98 | | |
| 99 | | |
| 100 | | static int tx0_read(tx0_state *cpustate, offs_t address) |
| 76 | int tx0_device::tx0_read(offs_t address) |
| 101 | 77 | { |
| 102 | | if ((address >= 16) || (cpustate->gbl_cm_sel) || ((cpustate->cm_sel >> address) & 1)) |
| 78 | if ((address >= 16) || (m_gbl_cm_sel) || ((m_cm_sel >> address) & 1)) |
| 103 | 79 | /* core memory (CM) */ |
| 104 | 80 | return READ_TX0_18BIT(address); |
| 105 | | else if ((cpustate->lr_sel >> address) & 1) |
| 81 | else if ((m_lr_sel >> address) & 1) |
| 106 | 82 | /* live register (LR) */ |
| 107 | 83 | return LR; |
| 108 | 84 | |
| 109 | 85 | /* toggle switch storage (TSS) */ |
| 110 | | return cpustate->tss[address]; |
| 86 | return m_tss[address]; |
| 111 | 87 | } |
| 112 | 88 | |
| 113 | | static void tx0_write(tx0_state *cpustate, offs_t address, int data) |
| 89 | void tx0_device::tx0_write(offs_t address, int data) |
| 114 | 90 | { |
| 115 | | if ((address >= 16) || (cpustate->gbl_cm_sel) || ((cpustate->cm_sel >> address) & 1)) |
| 91 | if ((address >= 16) || (m_gbl_cm_sel) || ((m_cm_sel >> address) & 1)) |
| 116 | 92 | /* core memory (CM) */ |
| 117 | 93 | WRITE_TX0_18BIT(address, data); |
| 118 | | else if ((cpustate->lr_sel >> address) & 1) |
| 94 | else if ((m_lr_sel >> address) & 1) |
| 119 | 95 | /* live register (LR) */ |
| 120 | 96 | LR = data; |
| 121 | 97 | else |
| r26748 | r26749 | |
| 124 | 100 | ; |
| 125 | 101 | } |
| 126 | 102 | |
| 127 | | static void tx0_init_common(legacy_cpu_device *device, device_irq_acknowledge_callback irqcallback, int is_64kw) |
| 103 | |
| 104 | void tx0_device::device_start() |
| 128 | 105 | { |
| 129 | | tx0_state *cpustate = get_safe_token(device); |
| 106 | m_mbr = 0; |
| 107 | m_ac = 0; |
| 108 | m_mar = 0; |
| 109 | m_lr = 0; |
| 110 | m_xr = 0; |
| 111 | m_pf = 0; |
| 112 | m_tbr = 0; |
| 113 | m_tac = 0; |
| 114 | for ( int i = 0; i < 16; i++ ) |
| 115 | { |
| 116 | m_tss[i] = 0; |
| 117 | } |
| 118 | m_cm_sel = 0; |
| 119 | m_lr_sel = 0; |
| 120 | m_gbl_cm_sel = 0; |
| 121 | m_stop_cyc0 = 0; |
| 122 | m_stop_cyc1 = 0; |
| 123 | m_cycle = 0; |
| 130 | 124 | |
| 131 | | /* clean-up */ |
| 132 | | cpustate->iface = (const tx0_reset_param_t *)device->static_config(); |
| 125 | // Resolve callbacks |
| 126 | m_cpy_handler.resolve(); |
| 127 | m_r1l_handler.resolve(); |
| 128 | m_dis_handler.resolve(); |
| 129 | m_r3l_handler.resolve(); |
| 130 | m_prt_handler.resolve(); |
| 131 | m_rsv_handler.resolve(); |
| 132 | m_p6h_handler.resolve(); |
| 133 | m_p7h_handler.resolve(); |
| 134 | m_sel_handler.resolve(); |
| 135 | m_io_reset_callback.resolve(); |
| 133 | 136 | |
| 134 | | cpustate->address_mask = is_64kw ? ADDRESS_MASK_64KW : ADDRESS_MASK_8KW; |
| 135 | | cpustate->ir_mask = is_64kw ? 03 : 037; |
| 137 | m_program = &space(AS_PROGRAM); |
| 136 | 138 | |
| 137 | | cpustate->device = device; |
| 138 | | cpustate->program = &device->space(AS_PROGRAM); |
| 139 | | } |
| 139 | save_item(NAME(m_mbr)); |
| 140 | save_item(NAME(m_ac)); |
| 141 | save_item(NAME(m_mar)); |
| 142 | save_item(NAME(m_pc)); |
| 143 | save_item(NAME(m_ir)); |
| 144 | save_item(NAME(m_lr)); |
| 145 | save_item(NAME(m_xr)); |
| 146 | save_item(NAME(m_pf)); |
| 147 | save_item(NAME(m_tbr)); |
| 148 | save_item(NAME(m_tac)); |
| 149 | save_item(NAME(m_tss)); |
| 150 | save_item(NAME(m_cm_sel)); |
| 151 | save_item(NAME(m_lr_sel)); |
| 152 | save_item(NAME(m_gbl_cm_sel)); |
| 153 | save_item(NAME(m_stop_cyc0)); |
| 154 | save_item(NAME(m_stop_cyc1)); |
| 155 | save_item(NAME(m_run)); |
| 156 | save_item(NAME(m_rim)); |
| 157 | save_item(NAME(m_cycle)); |
| 158 | save_item(NAME(m_ioh)); |
| 159 | save_item(NAME(m_ios)); |
| 160 | save_item(NAME(m_rim_step)); |
| 140 | 161 | |
| 141 | | static CPU_INIT( tx0_64kw ) |
| 142 | | { |
| 143 | | tx0_init_common(device, irqcallback, 1); |
| 144 | | } |
| 162 | // Register state for debugger |
| 163 | state_add( TX0_PC, "PC", m_pc ).mask(m_address_mask).formatstr("0%06O"); |
| 164 | state_add( TX0_IR, "IR", m_ir ).mask(m_ir_mask) .formatstr("0%02O"); |
| 165 | state_add( TX0_MBR, "MBR", m_mbr ).mask(0777777) .formatstr("0%06O"); |
| 166 | state_add( TX0_MAR, "MAR", m_mar ).mask(m_address_mask).formatstr("0%06O"); |
| 167 | state_add( TX0_AC, "AC", m_ac ).mask(0777777) .formatstr("0%06O"); |
| 168 | state_add( TX0_LR, "LR", m_lr ).mask(0777777) .formatstr("0%06O"); |
| 169 | state_add( TX0_XR, "XR", m_xr ).mask(0037777) .formatstr("0%05O"); |
| 170 | state_add( TX0_PF, "PF", m_pf ).mask(077) .formatstr("0%02O"); |
| 171 | state_add( TX0_TBR, "TBR", m_tbr ).mask(0777777) .formatstr("0%06O"); |
| 172 | state_add( TX0_TAC, "TAC", m_tac ).mask(0777777) .formatstr("0%06O"); |
| 173 | state_add( TX0_TSS00, "TSS00", m_tss[000] ).mask(0777777) .formatstr("0%06O"); |
| 174 | state_add( TX0_TSS01, "TSS01", m_tss[001] ).mask(0777777) .formatstr("0%06O"); |
| 175 | state_add( TX0_TSS02, "TSS02", m_tss[002] ).mask(0777777) .formatstr("0%06O"); |
| 176 | state_add( TX0_TSS03, "TSS03", m_tss[003] ).mask(0777777) .formatstr("0%06O"); |
| 177 | state_add( TX0_TSS04, "TSS04", m_tss[004] ).mask(0777777) .formatstr("0%06O"); |
| 178 | state_add( TX0_TSS05, "TSS05", m_tss[005] ).mask(0777777) .formatstr("0%06O"); |
| 179 | state_add( TX0_TSS06, "TSS06", m_tss[006] ).mask(0777777) .formatstr("0%06O"); |
| 180 | state_add( TX0_TSS07, "TSS07", m_tss[007] ).mask(0777777) .formatstr("0%06O"); |
| 181 | state_add( TX0_TSS10, "TSS10", m_tss[010] ).mask(0777777) .formatstr("0%06O"); |
| 182 | state_add( TX0_TSS11, "TSS11", m_tss[011] ).mask(0777777) .formatstr("0%06O"); |
| 183 | state_add( TX0_TSS12, "TSS12", m_tss[012] ).mask(0777777) .formatstr("0%06O"); |
| 184 | state_add( TX0_TSS13, "TSS13", m_tss[013] ).mask(0777777) .formatstr("0%06O"); |
| 185 | state_add( TX0_TSS14, "TSS14", m_tss[014] ).mask(0777777) .formatstr("0%06O"); |
| 186 | state_add( TX0_TSS15, "TSS15", m_tss[015] ).mask(0777777) .formatstr("0%06O"); |
| 187 | state_add( TX0_TSS16, "TSS16", m_tss[016] ).mask(0777777) .formatstr("0%06O"); |
| 188 | state_add( TX0_TSS17, "TSS17", m_tss[017] ).mask(0777777) .formatstr("0%06O"); |
| 189 | state_add( TX0_CM_SEL, "CMSEL", m_cm_sel ).mask(0177777) .formatstr("0%06O"); |
| 190 | state_add( TX0_LR_SEL, "LRSEL", m_lr_sel ).mask(0177777) .formatstr("0%06O"); |
| 191 | state_add( TX0_GBL_CM_SEL, "GBLCMSEL", m_gbl_cm_sel ).mask(1) .formatstr("%1X"); |
| 192 | state_add( TX0_STOP_CYC0, "STOPCYC0", m_stop_cyc0 ).mask(1) .formatstr("%1X"); |
| 193 | state_add( TX0_STOP_CYC1, "STOPCYC1", m_stop_cyc1 ).mask(1) .formatstr("%1X"); |
| 194 | state_add( TX0_RUN, "RUN", m_run ).mask(1) .formatstr("%1X"); |
| 195 | state_add( TX0_RIM, "RIM", m_rim ).mask(1) .formatstr("%1X"); |
| 196 | state_add( TX0_CYCLE, "CYCLE", m_cycle ) .formatstr("%1X"); |
| 197 | state_add( TX0_IOH, "IOH", m_ioh ) .formatstr("%1X"); |
| 198 | state_add( TX0_IOS, "IOS", m_ios ).mask(1) .formatstr("%1X"); |
| 145 | 199 | |
| 146 | | static CPU_INIT( tx0_8kw) |
| 147 | | { |
| 148 | | tx0_init_common(device, irqcallback, 0); |
| 200 | state_add(STATE_GENPC, "GENPC", m_pc).formatstr("0%06O").noshow(); |
| 201 | state_add(STATE_GENFLAGS, "GENFLAGS", m_ir).noshow(); |
| 202 | |
| 203 | m_icountptr = &m_icount; |
| 149 | 204 | } |
| 150 | 205 | |
| 151 | | static CPU_RESET( tx0 ) |
| 152 | | { |
| 153 | | tx0_state *cpustate = get_safe_token(device); |
| 154 | 206 | |
| 207 | void tx0_device::device_reset() |
| 208 | { |
| 155 | 209 | /* reset CPU flip-flops */ |
| 156 | | pulse_reset(device); |
| 210 | pulse_reset(); |
| 157 | 211 | |
| 158 | | cpustate->gbl_cm_sel = 1; /* HACK */ |
| 212 | m_gbl_cm_sel = 1; /* HACK */ |
| 159 | 213 | } |
| 160 | 214 | |
| 161 | | /* execute instructions on this CPU until icount expires */ |
| 162 | | static CPU_EXECUTE( tx0_64kw ) |
| 215 | |
| 216 | void tx0_device::call_io_handler(int io_handler) |
| 163 | 217 | { |
| 164 | | tx0_state *cpustate = get_safe_token(device); |
| 218 | /* data will be transferred to AC */ |
| 219 | switch (io_handler) |
| 220 | { |
| 221 | case 0: m_cpy_handler(ASSERT_LINE); break; |
| 222 | case 1: m_r1l_handler(ASSERT_LINE); break; |
| 223 | case 2: m_dis_handler(ASSERT_LINE); break; |
| 224 | case 3: m_r3l_handler(ASSERT_LINE); break; |
| 225 | case 4: m_prt_handler(ASSERT_LINE); break; |
| 226 | case 5: m_rsv_handler(ASSERT_LINE); break; |
| 227 | case 6: m_p6h_handler(ASSERT_LINE); break; |
| 228 | case 7: m_p7h_handler(ASSERT_LINE); break; |
| 229 | } |
| 230 | } |
| 165 | 231 | |
| 232 | |
| 233 | /* execute instructions on this CPU until icount expires */ |
| 234 | void tx0_64kw_device::execute_run() |
| 235 | { |
| 166 | 236 | do |
| 167 | 237 | { |
| 168 | | debugger_instruction_hook(device, PC); |
| 238 | debugger_instruction_hook(this, PC); |
| 169 | 239 | |
| 170 | 240 | |
| 171 | | if (cpustate->ioh && cpustate->ios) |
| 241 | if (m_ioh && m_ios) |
| 172 | 242 | { |
| 173 | | cpustate->ioh = 0; |
| 243 | m_ioh = 0; |
| 174 | 244 | } |
| 175 | 245 | |
| 176 | 246 | |
| 177 | | if ((! cpustate->run) && (! cpustate->rim)) |
| 178 | | cpustate->icount = 0; /* if processor is stopped, just burn cycles */ |
| 179 | | else if (cpustate->rim) |
| 247 | if ((! m_run) && (! m_rim)) |
| 248 | m_icount = 0; /* if processor is stopped, just burn cycles */ |
| 249 | else if (m_rim) |
| 180 | 250 | { |
| 181 | | switch (cpustate->rim_step) |
| 251 | switch (m_rim_step) |
| 182 | 252 | { |
| 183 | 253 | case 0: |
| 184 | 254 | /* read first word as instruction */ |
| 185 | 255 | AC = 0; |
| 186 | | if (cpustate->iface->io_handlers[io_handler_rim]) |
| 187 | | (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ |
| 188 | | cpustate->rim_step = 1; |
| 189 | | cpustate->ios = 0; |
| 256 | call_io_handler(io_handler_rim); |
| 257 | m_rim_step = 1; |
| 258 | m_ios = 0; |
| 190 | 259 | break; |
| 191 | 260 | |
| 192 | 261 | case 1: |
| 193 | | if (! cpustate->ios) |
| 262 | if (! m_ios) |
| 194 | 263 | { /* transfer incomplete: wait some more */ |
| 195 | | cpustate->icount = 0; |
| 264 | m_icount = 0; |
| 196 | 265 | } |
| 197 | 266 | else |
| 198 | 267 | { /* data transfer complete */ |
| 199 | | cpustate->ios = 0; |
| 268 | m_ios = 0; |
| 200 | 269 | |
| 201 | 270 | MBR = AC; |
| 202 | 271 | IR = MBR >> 16; /* basic opcode */ |
| 203 | 272 | if ((IR == 2) || (IR == 1)) /* trn or add instruction? */ |
| 204 | 273 | { |
| 205 | 274 | PC = MBR & ADDRESS_MASK_64KW; |
| 206 | | cpustate->rim = 0; /* exit read-in mode */ |
| 207 | | cpustate->run = (IR == 2) ? 1 : 0; /* stop if add instruction */ |
| 208 | | cpustate->rim_step = 0; |
| 275 | m_rim = 0; /* exit read-in mode */ |
| 276 | m_run = (IR == 2) ? 1 : 0; /* stop if add instruction */ |
| 277 | m_rim_step = 0; |
| 209 | 278 | } |
| 210 | 279 | else if ((IR == 0) || (IR == 3)) /* sto or opr instruction? */ |
| 211 | 280 | { |
| 212 | 281 | MAR = MBR & ADDRESS_MASK_64KW; |
| 213 | | cpustate->rim_step = 2; |
| 282 | m_rim_step = 2; |
| 214 | 283 | } |
| 215 | 284 | } |
| 216 | 285 | break; |
| r26748 | r26749 | |
| 218 | 287 | case 2: |
| 219 | 288 | /* read second word as data */ |
| 220 | 289 | AC = 0; |
| 221 | | if (cpustate->iface->io_handlers[io_handler_rim]) |
| 222 | | (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ |
| 223 | | cpustate->rim_step = 3; |
| 224 | | cpustate->ios = 0; |
| 290 | call_io_handler(io_handler_rim); |
| 291 | m_rim_step = 3; |
| 292 | m_ios = 0; |
| 225 | 293 | break; |
| 226 | 294 | |
| 227 | 295 | case 3: |
| 228 | | if (! cpustate->ios) |
| 296 | if (! m_ios) |
| 229 | 297 | { /* transfer incomplete: wait some more */ |
| 230 | | cpustate->icount = 0; |
| 298 | m_icount = 0; |
| 231 | 299 | } |
| 232 | 300 | else |
| 233 | 301 | { /* data transfer complete */ |
| 234 | | cpustate->ios = 0; |
| 302 | m_ios = 0; |
| 235 | 303 | |
| 236 | | tx0_write(cpustate, MAR, MBR = AC); |
| 304 | tx0_write(MAR, MBR = AC); |
| 237 | 305 | |
| 238 | | cpustate->rim_step = 0; |
| 306 | m_rim_step = 0; |
| 239 | 307 | } |
| 240 | 308 | break; |
| 241 | 309 | } |
| 242 | 310 | } |
| 243 | 311 | else |
| 244 | 312 | { |
| 245 | | if (cpustate->cycle == 0) |
| 313 | if (m_cycle == 0) |
| 246 | 314 | { /* fetch new instruction */ |
| 247 | | MBR = tx0_read(cpustate, MAR = PC); |
| 315 | MBR = tx0_read(MAR = PC); |
| 248 | 316 | INCREMENT_PC_64KW; |
| 249 | 317 | IR = MBR >> 16; /* basic opcode */ |
| 250 | 318 | MAR = MBR & ADDRESS_MASK_64KW; |
| 251 | 319 | } |
| 252 | 320 | |
| 253 | | if (! cpustate->ioh) |
| 321 | if (! m_ioh) |
| 254 | 322 | { |
| 255 | | if ((cpustate->stop_cyc0 && (cpustate->cycle == 0)) |
| 256 | | || (cpustate->stop_cyc1 && (cpustate->cycle == 1))) |
| 257 | | cpustate->run = 0; |
| 323 | if ((m_stop_cyc0 && (m_cycle == 0)) |
| 324 | || (m_stop_cyc1 && (m_cycle == 1))) |
| 325 | m_run = 0; |
| 258 | 326 | |
| 259 | | execute_instruction_64kw(device); /* execute instruction */ |
| 327 | execute_instruction_64kw(); |
| 260 | 328 | } |
| 261 | 329 | |
| 262 | | cpustate->icount --; |
| 330 | m_icount --; |
| 263 | 331 | } |
| 264 | 332 | } |
| 265 | | while (cpustate->icount > 0); |
| 333 | while (m_icount > 0); |
| 266 | 334 | } |
| 267 | 335 | |
| 268 | 336 | /* execute instructions on this CPU until icount expires */ |
| 269 | | static CPU_EXECUTE( tx0_8kw ) |
| 337 | void tx0_8kw_device::execute_run() |
| 270 | 338 | { |
| 271 | | tx0_state *cpustate = get_safe_token(device); |
| 272 | | |
| 273 | 339 | do |
| 274 | 340 | { |
| 275 | | debugger_instruction_hook(device, PC); |
| 341 | debugger_instruction_hook(this, PC); |
| 276 | 342 | |
| 277 | 343 | |
| 278 | | if (cpustate->ioh && cpustate->ios) |
| 344 | if (m_ioh && m_ios) |
| 279 | 345 | { |
| 280 | | cpustate->ioh = 0; |
| 346 | m_ioh = 0; |
| 281 | 347 | } |
| 282 | 348 | |
| 283 | 349 | |
| 284 | | if ((! cpustate->run) && (! cpustate->rim)) |
| 285 | | cpustate->icount = 0; /* if processor is stopped, just burn cycles */ |
| 286 | | else if (cpustate->rim) |
| 350 | if ((! m_run) && (! m_rim)) |
| 351 | m_icount = 0; /* if processor is stopped, just burn cycles */ |
| 352 | else if (m_rim) |
| 287 | 353 | { |
| 288 | | switch (cpustate->rim_step) |
| 354 | switch (m_rim_step) |
| 289 | 355 | { |
| 290 | 356 | case 0: |
| 291 | 357 | /* read first word as instruction */ |
| 292 | 358 | AC = 0; |
| 293 | | if (cpustate->iface->io_handlers[io_handler_rim]) |
| 294 | | (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ |
| 295 | | cpustate->rim_step = 1; |
| 296 | | cpustate->ios = 0; |
| 359 | call_io_handler(io_handler_rim); |
| 360 | m_rim_step = 1; |
| 361 | m_ios = 0; |
| 297 | 362 | break; |
| 298 | 363 | |
| 299 | 364 | case 1: |
| 300 | | if (! cpustate->ios) |
| 365 | if (! m_ios) |
| 301 | 366 | { /* transfer incomplete: wait some more */ |
| 302 | | cpustate->icount = 0; |
| 367 | m_icount = 0; |
| 303 | 368 | } |
| 304 | 369 | else |
| 305 | 370 | { /* data transfer complete */ |
| 306 | | cpustate->ios = 0; |
| 371 | m_ios = 0; |
| 307 | 372 | |
| 308 | 373 | MBR = AC; |
| 309 | 374 | IR = MBR >> 13; /* basic opcode */ |
| 310 | 375 | if ((IR == 16) || (IR == 8)) /* trn or add instruction? */ |
| 311 | 376 | { |
| 312 | 377 | PC = MBR & ADDRESS_MASK_8KW; |
| 313 | | cpustate->rim = 0; /* exit read-in mode */ |
| 314 | | cpustate->run = (IR == 16) ? 1 : 0; /* stop if add instruction */ |
| 315 | | cpustate->rim_step = 0; |
| 378 | m_rim = 0; /* exit read-in mode */ |
| 379 | m_run = (IR == 16) ? 1 : 0; /* stop if add instruction */ |
| 380 | m_rim_step = 0; |
| 316 | 381 | } |
| 317 | 382 | else if ((IR == 0) || (IR == 24)) /* sto or opr instruction? */ |
| 318 | 383 | { |
| 319 | 384 | MAR = MBR & ADDRESS_MASK_8KW; |
| 320 | | cpustate->rim_step = 2; |
| 385 | m_rim_step = 2; |
| 321 | 386 | } |
| 322 | 387 | } |
| 323 | 388 | break; |
| r26748 | r26749 | |
| 325 | 390 | case 2: |
| 326 | 391 | /* read second word as data */ |
| 327 | 392 | AC = 0; |
| 328 | | if (cpustate->iface->io_handlers[io_handler_rim]) |
| 329 | | (*cpustate->iface->io_handlers[io_handler_rim])(device); /* data will be transferred to AC */ |
| 330 | | cpustate->rim_step = 3; |
| 331 | | cpustate->ios = 0; |
| 393 | call_io_handler(io_handler_rim); |
| 394 | m_rim_step = 3; |
| 395 | m_ios = 0; |
| 332 | 396 | break; |
| 333 | 397 | |
| 334 | 398 | case 3: |
| 335 | | if (! cpustate->ios) |
| 399 | if (! m_ios) |
| 336 | 400 | { /* transfer incomplete: wait some more */ |
| 337 | | cpustate->icount = 0; |
| 401 | m_icount = 0; |
| 338 | 402 | } |
| 339 | 403 | else |
| 340 | 404 | { /* data transfer complete */ |
| 341 | | cpustate->ios = 0; |
| 405 | m_ios = 0; |
| 342 | 406 | |
| 343 | | tx0_write(cpustate, MAR, MBR = AC); |
| 407 | tx0_write(MAR, MBR = AC); |
| 344 | 408 | |
| 345 | | cpustate->rim_step = 0; |
| 409 | m_rim_step = 0; |
| 346 | 410 | } |
| 347 | 411 | break; |
| 348 | 412 | } |
| 349 | 413 | } |
| 350 | 414 | else |
| 351 | 415 | { |
| 352 | | if (cpustate->cycle == 0) |
| 416 | if (m_cycle == 0) |
| 353 | 417 | { /* fetch new instruction */ |
| 354 | | MBR = tx0_read(cpustate, MAR = PC); |
| 418 | MBR = tx0_read(MAR = PC); |
| 355 | 419 | INCREMENT_PC_8KW; |
| 356 | 420 | IR = MBR >> 13; /* basic opcode */ |
| 357 | 421 | MAR = MBR & ADDRESS_MASK_8KW; |
| 358 | 422 | } |
| 359 | 423 | |
| 360 | | if (! cpustate->ioh) |
| 424 | if (! m_ioh) |
| 361 | 425 | { |
| 362 | | if ((cpustate->stop_cyc0 && (cpustate->cycle == 0)) |
| 363 | | || (cpustate->stop_cyc1 && (cpustate->cycle == 1))) |
| 364 | | cpustate->run = 0; |
| 426 | if ((m_stop_cyc0 && (m_cycle == 0)) |
| 427 | || (m_stop_cyc1 && (m_cycle == 1))) |
| 428 | m_run = 0; |
| 365 | 429 | |
| 366 | | execute_instruction_8kw(device); /* execute instruction */ |
| 430 | execute_instruction_8kw(); |
| 367 | 431 | } |
| 368 | 432 | |
| 369 | | cpustate->icount -= 1; |
| 433 | m_icount -= 1; |
| 370 | 434 | } |
| 371 | 435 | } |
| 372 | | while (cpustate->icount > 0); |
| 436 | while (m_icount > 0); |
| 373 | 437 | } |
| 374 | 438 | |
| 375 | 439 | |
| 376 | | static CPU_SET_INFO( tx0 ) |
| 377 | | { |
| 378 | | tx0_state *cpustate = get_safe_token(device); |
| 379 | | |
| 380 | | switch (state) |
| 381 | | { |
| 382 | | /* --- the following bits of info are set as 64-bit signed integers --- */ |
| 383 | | case CPUINFO_INT_SP: (void) info->i; /* no SP */ break; |
| 384 | | case CPUINFO_INT_PC: |
| 385 | | case CPUINFO_INT_REGISTER + TX0_PC: PC = info->i & cpustate->address_mask; break; |
| 386 | | case CPUINFO_INT_REGISTER + TX0_IR: IR = info->i & cpustate->ir_mask; /* weird idea */ break; |
| 387 | | case CPUINFO_INT_REGISTER + TX0_MBR: MBR = info->i & 0777777; break; |
| 388 | | case CPUINFO_INT_REGISTER + TX0_MAR: MAR = info->i & cpustate->address_mask; break; |
| 389 | | case CPUINFO_INT_REGISTER + TX0_AC: AC = info->i & 0777777; break; |
| 390 | | case CPUINFO_INT_REGISTER + TX0_LR: LR = info->i & 0777777; break; |
| 391 | | case CPUINFO_INT_REGISTER + TX0_XR: XR = info->i & 0037777; break; |
| 392 | | case CPUINFO_INT_REGISTER + TX0_PF: PF = info->i & 077; break; |
| 393 | | case CPUINFO_INT_REGISTER + TX0_TBR: cpustate->tbr = info->i & 0777777; break; |
| 394 | | case CPUINFO_INT_REGISTER + TX0_TAC: cpustate->tac = info->i & 0777777; break; |
| 395 | | case CPUINFO_INT_REGISTER + TX0_TSS00: |
| 396 | | case CPUINFO_INT_REGISTER + TX0_TSS01: |
| 397 | | case CPUINFO_INT_REGISTER + TX0_TSS02: |
| 398 | | case CPUINFO_INT_REGISTER + TX0_TSS03: |
| 399 | | case CPUINFO_INT_REGISTER + TX0_TSS04: |
| 400 | | case CPUINFO_INT_REGISTER + TX0_TSS05: |
| 401 | | case CPUINFO_INT_REGISTER + TX0_TSS06: |
| 402 | | case CPUINFO_INT_REGISTER + TX0_TSS07: |
| 403 | | case CPUINFO_INT_REGISTER + TX0_TSS10: |
| 404 | | case CPUINFO_INT_REGISTER + TX0_TSS11: |
| 405 | | case CPUINFO_INT_REGISTER + TX0_TSS12: |
| 406 | | case CPUINFO_INT_REGISTER + TX0_TSS13: |
| 407 | | case CPUINFO_INT_REGISTER + TX0_TSS14: |
| 408 | | case CPUINFO_INT_REGISTER + TX0_TSS15: |
| 409 | | case CPUINFO_INT_REGISTER + TX0_TSS16: |
| 410 | | case CPUINFO_INT_REGISTER + TX0_TSS17: cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)] = info->i & 0777777; break; |
| 411 | | case CPUINFO_INT_REGISTER + TX0_CM_SEL: cpustate->cm_sel = info->i & 0177777; break; |
| 412 | | case CPUINFO_INT_REGISTER + TX0_LR_SEL: cpustate->lr_sel = info->i & 0177777; break; |
| 413 | | case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: cpustate->gbl_cm_sel = info->i ? 1 : 0; break; |
| 414 | | case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: cpustate->stop_cyc0 = info->i ? 1 : 0; break; |
| 415 | | case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: cpustate->stop_cyc1 = info->i ? 1 : 0; break; |
| 416 | | case CPUINFO_INT_REGISTER + TX0_RUN: cpustate->run = info->i ? 1 : 0; break; |
| 417 | | case CPUINFO_INT_REGISTER + TX0_RIM: cpustate->rim = info->i ? 1 : 0; break; |
| 418 | | case CPUINFO_INT_REGISTER + TX0_CYCLE: if (LOG) logerror("tx0_set_reg to cycle counter ignored\n");/* no way!*/ break; |
| 419 | | case CPUINFO_INT_REGISTER + TX0_IOH: if (LOG) logerror("tx0_set_reg to ioh flip-flop ignored\n");/* no way!*/ break; |
| 420 | | case CPUINFO_INT_REGISTER + TX0_IOS: cpustate->ios = info->i ? 1 : 0; break; |
| 421 | | case CPUINFO_INT_REGISTER + TX0_RESET: pulse_reset(device); break; |
| 422 | | case CPUINFO_INT_REGISTER + TX0_IO_COMPLETE:cpustate->ios = 1; break; |
| 423 | | } |
| 424 | | } |
| 425 | | |
| 426 | | |
| 427 | | CPU_GET_INFO( tx0_64kw ) |
| 428 | | { |
| 429 | | tx0_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL; |
| 430 | | |
| 431 | | switch (state) |
| 432 | | { |
| 433 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 434 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tx0_state); break; |
| 435 | | case CPUINFO_INT_INPUT_LINES: info->i = 0; break; |
| 436 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 437 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ break; |
| 438 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 439 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 440 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break; |
| 441 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; |
| 442 | | case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; |
| 443 | | case CPUINFO_INT_MAX_CYCLES: info->i = 3; break; |
| 444 | | |
| 445 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
| 446 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break; |
| 447 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break; |
| 448 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
| 449 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
| 450 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 451 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; |
| 452 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; |
| 453 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
| 454 | | |
| 455 | | case CPUINFO_INT_SP: info->i = 0; /* no SP */ break; |
| 456 | | case CPUINFO_INT_PC: info->i = PC; break; |
| 457 | | case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break; |
| 458 | | |
| 459 | | case CPUINFO_INT_REGISTER + TX0_PC: info->i = PC; break; |
| 460 | | case CPUINFO_INT_REGISTER + TX0_IR: info->i = IR; break; |
| 461 | | case CPUINFO_INT_REGISTER + TX0_MBR: info->i = MBR; break; |
| 462 | | case CPUINFO_INT_REGISTER + TX0_MAR: info->i = MAR; break; |
| 463 | | case CPUINFO_INT_REGISTER + TX0_AC: info->i = AC; break; |
| 464 | | case CPUINFO_INT_REGISTER + TX0_LR: info->i = LR; break; |
| 465 | | case CPUINFO_INT_REGISTER + TX0_XR: info->i = XR; break; |
| 466 | | case CPUINFO_INT_REGISTER + TX0_PF: info->i = PF; break; |
| 467 | | case CPUINFO_INT_REGISTER + TX0_TBR: info->i = cpustate->tbr; break; |
| 468 | | case CPUINFO_INT_REGISTER + TX0_TAC: info->i = cpustate->tac; break; |
| 469 | | case CPUINFO_INT_REGISTER + TX0_TSS00: |
| 470 | | case CPUINFO_INT_REGISTER + TX0_TSS01: |
| 471 | | case CPUINFO_INT_REGISTER + TX0_TSS02: |
| 472 | | case CPUINFO_INT_REGISTER + TX0_TSS03: |
| 473 | | case CPUINFO_INT_REGISTER + TX0_TSS04: |
| 474 | | case CPUINFO_INT_REGISTER + TX0_TSS05: |
| 475 | | case CPUINFO_INT_REGISTER + TX0_TSS06: |
| 476 | | case CPUINFO_INT_REGISTER + TX0_TSS07: |
| 477 | | case CPUINFO_INT_REGISTER + TX0_TSS10: |
| 478 | | case CPUINFO_INT_REGISTER + TX0_TSS11: |
| 479 | | case CPUINFO_INT_REGISTER + TX0_TSS12: |
| 480 | | case CPUINFO_INT_REGISTER + TX0_TSS13: |
| 481 | | case CPUINFO_INT_REGISTER + TX0_TSS14: |
| 482 | | case CPUINFO_INT_REGISTER + TX0_TSS15: |
| 483 | | case CPUINFO_INT_REGISTER + TX0_TSS16: |
| 484 | | case CPUINFO_INT_REGISTER + TX0_TSS17: info->i = cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)]; break; |
| 485 | | case CPUINFO_INT_REGISTER + TX0_CM_SEL: info->i = cpustate->cm_sel; break; |
| 486 | | case CPUINFO_INT_REGISTER + TX0_LR_SEL: info->i = cpustate->lr_sel; break; |
| 487 | | case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: info->i = cpustate->gbl_cm_sel; break; |
| 488 | | case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: info->i = cpustate->stop_cyc0; break; |
| 489 | | case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: info->i = cpustate->stop_cyc1; break; |
| 490 | | case CPUINFO_INT_REGISTER + TX0_RUN: info->i = cpustate->run; break; |
| 491 | | case CPUINFO_INT_REGISTER + TX0_RIM: info->i = cpustate->rim; break; |
| 492 | | case CPUINFO_INT_REGISTER + TX0_CYCLE: info->i = cpustate->cycle; break; |
| 493 | | case CPUINFO_INT_REGISTER + TX0_IOH: info->i = cpustate->ioh; break; |
| 494 | | case CPUINFO_INT_REGISTER + TX0_IOS: info->i = cpustate->ios; break; |
| 495 | | |
| 496 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 497 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tx0); break; |
| 498 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tx0_64kw); break; |
| 499 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tx0); break; |
| 500 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tx0_64kw); break; |
| 501 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
| 502 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tx0_64kw); break; |
| 503 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; |
| 504 | | |
| 505 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 506 | | case CPUINFO_STR_NAME: strcpy(info->s, "TX-0"); break; |
| 507 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "tx0_64kw_cpu"); break; |
| 508 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "TX-0"); break; |
| 509 | | case CPUINFO_STR_VERSION: strcpy(info->s, "1.0"); break; |
| 510 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 511 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break; |
| 512 | | |
| 513 | | case CPUINFO_STR_FLAGS: strcpy(info->s, ""); break; |
| 514 | | |
| 515 | | case CPUINFO_STR_REGISTER + TX0_PC: sprintf(info->s, "PC:0%06o", PC); break; |
| 516 | | case CPUINFO_STR_REGISTER + TX0_IR: sprintf(info->s, "IR:0%02o", IR); break; |
| 517 | | case CPUINFO_STR_REGISTER + TX0_MBR: sprintf(info->s, "MBR:0%06o", MBR); break; |
| 518 | | case CPUINFO_STR_REGISTER + TX0_MAR: sprintf(info->s, "MAR:0%06o", MAR); break; |
| 519 | | case CPUINFO_STR_REGISTER + TX0_AC: sprintf(info->s, "AC:0%06o", AC); break; |
| 520 | | case CPUINFO_STR_REGISTER + TX0_LR: sprintf(info->s, "LR:0%06o", LR); break; |
| 521 | | case CPUINFO_STR_REGISTER + TX0_XR: sprintf(info->s, "XR:0%05o", XR); break; |
| 522 | | case CPUINFO_STR_REGISTER + TX0_PF: sprintf(info->s, "PF:0%02o", PF); break; |
| 523 | | case CPUINFO_STR_REGISTER + TX0_TBR: sprintf(info->s, "TBR:0%06o", cpustate->tbr); break; |
| 524 | | case CPUINFO_STR_REGISTER + TX0_TAC: sprintf(info->s, "TAC:0%06o", cpustate->tac); break; |
| 525 | | case CPUINFO_STR_REGISTER + TX0_TSS00: |
| 526 | | case CPUINFO_STR_REGISTER + TX0_TSS01: |
| 527 | | case CPUINFO_STR_REGISTER + TX0_TSS02: |
| 528 | | case CPUINFO_STR_REGISTER + TX0_TSS03: |
| 529 | | case CPUINFO_STR_REGISTER + TX0_TSS04: |
| 530 | | case CPUINFO_STR_REGISTER + TX0_TSS05: |
| 531 | | case CPUINFO_STR_REGISTER + TX0_TSS06: |
| 532 | | case CPUINFO_STR_REGISTER + TX0_TSS07: |
| 533 | | case CPUINFO_STR_REGISTER + TX0_TSS10: |
| 534 | | case CPUINFO_STR_REGISTER + TX0_TSS11: |
| 535 | | case CPUINFO_STR_REGISTER + TX0_TSS12: |
| 536 | | case CPUINFO_STR_REGISTER + TX0_TSS13: |
| 537 | | case CPUINFO_STR_REGISTER + TX0_TSS14: |
| 538 | | case CPUINFO_STR_REGISTER + TX0_TSS15: |
| 539 | | case CPUINFO_STR_REGISTER + TX0_TSS16: |
| 540 | | 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; |
| 541 | | case CPUINFO_STR_REGISTER + TX0_CM_SEL: sprintf(info->s, "CMSEL:0%06o", cpustate->cm_sel); break; |
| 542 | | case CPUINFO_STR_REGISTER + TX0_LR_SEL: sprintf(info->s, "LRSEL:0%06o", cpustate->lr_sel); break; |
| 543 | | case CPUINFO_STR_REGISTER + TX0_GBL_CM_SEL: sprintf(info->s, "GBLCMSEL:%X", cpustate->gbl_cm_sel); break; |
| 544 | | case CPUINFO_STR_REGISTER + TX0_STOP_CYC0: sprintf(info->s, "STOPCYC0:%X", cpustate->stop_cyc0); break; |
| 545 | | case CPUINFO_STR_REGISTER + TX0_STOP_CYC1: sprintf(info->s, "STOPCYC1:%X", cpustate->stop_cyc1); break; |
| 546 | | case CPUINFO_STR_REGISTER + TX0_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break; |
| 547 | | case CPUINFO_STR_REGISTER + TX0_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break; |
| 548 | | case CPUINFO_STR_REGISTER + TX0_CYCLE: sprintf(info->s, "CYCLE:%X", cpustate->cycle); break; |
| 549 | | case CPUINFO_STR_REGISTER + TX0_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break; |
| 550 | | case CPUINFO_STR_REGISTER + TX0_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break; |
| 551 | | case CPUINFO_IS_OCTAL: info->i = true; break; |
| 552 | | } |
| 553 | | } |
| 554 | | |
| 555 | | CPU_GET_INFO( tx0_8kw ) |
| 556 | | { |
| 557 | | tx0_state *cpustate = ( device != NULL && device->token() != NULL ) ? get_safe_token(device) : NULL; |
| 558 | | |
| 559 | | switch (state) |
| 560 | | { |
| 561 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 562 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tx0_state); break; |
| 563 | | case CPUINFO_INT_INPUT_LINES: info->i = 0; break; |
| 564 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 565 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; /*don't care*/ break; |
| 566 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 567 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 568 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break; |
| 569 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; |
| 570 | | case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; |
| 571 | | case CPUINFO_INT_MAX_CYCLES: info->i = 3; break; |
| 572 | | |
| 573 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 32; break; |
| 574 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 13; break; |
| 575 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -2; break; |
| 576 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
| 577 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
| 578 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 579 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; |
| 580 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; |
| 581 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
| 582 | | |
| 583 | | case CPUINFO_INT_SP: info->i = 0; /* no SP */ break; |
| 584 | | case CPUINFO_INT_PC: info->i = PC; break; |
| 585 | | case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* TODO??? */ break; |
| 586 | | |
| 587 | | case CPUINFO_INT_REGISTER + TX0_PC: info->i = PC; break; |
| 588 | | case CPUINFO_INT_REGISTER + TX0_IR: info->i = IR; break; |
| 589 | | case CPUINFO_INT_REGISTER + TX0_MBR: info->i = MBR; break; |
| 590 | | case CPUINFO_INT_REGISTER + TX0_MAR: info->i = MAR; break; |
| 591 | | case CPUINFO_INT_REGISTER + TX0_AC: info->i = AC; break; |
| 592 | | case CPUINFO_INT_REGISTER + TX0_LR: info->i = LR; break; |
| 593 | | case CPUINFO_INT_REGISTER + TX0_XR: info->i = XR; break; |
| 594 | | case CPUINFO_INT_REGISTER + TX0_PF: info->i = PF; break; |
| 595 | | case CPUINFO_INT_REGISTER + TX0_TBR: info->i = cpustate->tbr; break; |
| 596 | | case CPUINFO_INT_REGISTER + TX0_TAC: info->i = cpustate->tac; break; |
| 597 | | case CPUINFO_INT_REGISTER + TX0_TSS00: |
| 598 | | case CPUINFO_INT_REGISTER + TX0_TSS01: |
| 599 | | case CPUINFO_INT_REGISTER + TX0_TSS02: |
| 600 | | case CPUINFO_INT_REGISTER + TX0_TSS03: |
| 601 | | case CPUINFO_INT_REGISTER + TX0_TSS04: |
| 602 | | case CPUINFO_INT_REGISTER + TX0_TSS05: |
| 603 | | case CPUINFO_INT_REGISTER + TX0_TSS06: |
| 604 | | case CPUINFO_INT_REGISTER + TX0_TSS07: |
| 605 | | case CPUINFO_INT_REGISTER + TX0_TSS10: |
| 606 | | case CPUINFO_INT_REGISTER + TX0_TSS11: |
| 607 | | case CPUINFO_INT_REGISTER + TX0_TSS12: |
| 608 | | case CPUINFO_INT_REGISTER + TX0_TSS13: |
| 609 | | case CPUINFO_INT_REGISTER + TX0_TSS14: |
| 610 | | case CPUINFO_INT_REGISTER + TX0_TSS15: |
| 611 | | case CPUINFO_INT_REGISTER + TX0_TSS16: |
| 612 | | case CPUINFO_INT_REGISTER + TX0_TSS17: info->i = cpustate->tss[state-(CPUINFO_INT_REGISTER + TX0_TSS00)]; break; |
| 613 | | case CPUINFO_INT_REGISTER + TX0_CM_SEL: info->i = cpustate->cm_sel; break; |
| 614 | | case CPUINFO_INT_REGISTER + TX0_LR_SEL: info->i = cpustate->lr_sel; break; |
| 615 | | case CPUINFO_INT_REGISTER + TX0_GBL_CM_SEL: info->i = cpustate->gbl_cm_sel; break; |
| 616 | | case CPUINFO_INT_REGISTER + TX0_STOP_CYC0: info->i = cpustate->stop_cyc0; break; |
| 617 | | case CPUINFO_INT_REGISTER + TX0_STOP_CYC1: info->i = cpustate->stop_cyc1; break; |
| 618 | | case CPUINFO_INT_REGISTER + TX0_RUN: info->i = cpustate->run; break; |
| 619 | | case CPUINFO_INT_REGISTER + TX0_RIM: info->i = cpustate->rim; break; |
| 620 | | case CPUINFO_INT_REGISTER + TX0_CYCLE: info->i = cpustate->cycle; break; |
| 621 | | case CPUINFO_INT_REGISTER + TX0_IOH: info->i = cpustate->ioh; break; |
| 622 | | case CPUINFO_INT_REGISTER + TX0_IOS: info->i = cpustate->ios; break; |
| 623 | | |
| 624 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 625 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(tx0); break; |
| 626 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(tx0_8kw); break; |
| 627 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(tx0); break; |
| 628 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(tx0_8kw); break; |
| 629 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
| 630 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(tx0_8kw); break; |
| 631 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; |
| 632 | | |
| 633 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 634 | | case CPUINFO_STR_NAME: strcpy(info->s, "TX-0"); break; |
| 635 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "tx0_8kw_cpu"); break; |
| 636 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "TX-0"); break; |
| 637 | | case CPUINFO_STR_VERSION: strcpy(info->s, "1.0"); break; |
| 638 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 639 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Raphael Nabet"); break; |
| 640 | | |
| 641 | | case CPUINFO_STR_FLAGS: strcpy(info->s, ""); break; |
| 642 | | |
| 643 | | case CPUINFO_STR_REGISTER + TX0_PC: sprintf(info->s, "PC:0%06o", PC); break; |
| 644 | | case CPUINFO_STR_REGISTER + TX0_IR: sprintf(info->s, "IR:0%02o", IR); break; |
| 645 | | case CPUINFO_STR_REGISTER + TX0_MBR: sprintf(info->s, "MBR:0%06o", MBR); break; |
| 646 | | case CPUINFO_STR_REGISTER + TX0_MAR: sprintf(info->s, "MAR:0%06o", MAR); break; |
| 647 | | case CPUINFO_STR_REGISTER + TX0_AC: sprintf(info->s, "AC:0%06o", AC); break; |
| 648 | | case CPUINFO_STR_REGISTER + TX0_LR: sprintf(info->s, "LR:0%06o", LR); break; |
| 649 | | case CPUINFO_STR_REGISTER + TX0_XR: sprintf(info->s, "XR:0%05o", XR); break; |
| 650 | | case CPUINFO_STR_REGISTER + TX0_PF: sprintf(info->s, "PF:0%02o", PF); break; |
| 651 | | case CPUINFO_STR_REGISTER + TX0_TBR: sprintf(info->s, "TBR:0%06o", cpustate->tbr); break; |
| 652 | | case CPUINFO_STR_REGISTER + TX0_TAC: sprintf(info->s, "TAC:0%06o", cpustate->tac); break; |
| 653 | | case CPUINFO_STR_REGISTER + TX0_TSS00: |
| 654 | | case CPUINFO_STR_REGISTER + TX0_TSS01: |
| 655 | | case CPUINFO_STR_REGISTER + TX0_TSS02: |
| 656 | | case CPUINFO_STR_REGISTER + TX0_TSS03: |
| 657 | | case CPUINFO_STR_REGISTER + TX0_TSS04: |
| 658 | | case CPUINFO_STR_REGISTER + TX0_TSS05: |
| 659 | | case CPUINFO_STR_REGISTER + TX0_TSS06: |
| 660 | | case CPUINFO_STR_REGISTER + TX0_TSS07: |
| 661 | | case CPUINFO_STR_REGISTER + TX0_TSS10: |
| 662 | | case CPUINFO_STR_REGISTER + TX0_TSS11: |
| 663 | | case CPUINFO_STR_REGISTER + TX0_TSS12: |
| 664 | | case CPUINFO_STR_REGISTER + TX0_TSS13: |
| 665 | | case CPUINFO_STR_REGISTER + TX0_TSS14: |
| 666 | | case CPUINFO_STR_REGISTER + TX0_TSS15: |
| 667 | | case CPUINFO_STR_REGISTER + TX0_TSS16: |
| 668 | | 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; |
| 669 | | case CPUINFO_STR_REGISTER + TX0_CM_SEL: sprintf(info->s, "CMSEL:0%06o", cpustate->cm_sel); break; |
| 670 | | case CPUINFO_STR_REGISTER + TX0_LR_SEL: sprintf(info->s, "LRSEL:0%06o", cpustate->lr_sel); break; |
| 671 | | case CPUINFO_STR_REGISTER + TX0_GBL_CM_SEL: sprintf(info->s, "GBLCMSEL:%X", cpustate->gbl_cm_sel); break; |
| 672 | | case CPUINFO_STR_REGISTER + TX0_STOP_CYC0: sprintf(info->s, "STOPCYC0:%X", cpustate->stop_cyc0); break; |
| 673 | | case CPUINFO_STR_REGISTER + TX0_STOP_CYC1: sprintf(info->s, "STOPCYC1:%X", cpustate->stop_cyc1); break; |
| 674 | | case CPUINFO_STR_REGISTER + TX0_RUN: sprintf(info->s, "RUN:%X", cpustate->run); break; |
| 675 | | case CPUINFO_STR_REGISTER + TX0_RIM: sprintf(info->s, "RIM:%X", cpustate->rim); break; |
| 676 | | case CPUINFO_STR_REGISTER + TX0_CYCLE: sprintf(info->s, "CYCLE:%X", cpustate->cycle); break; |
| 677 | | case CPUINFO_STR_REGISTER + TX0_IOH: sprintf(info->s, "IOH:%X", cpustate->ioh); break; |
| 678 | | case CPUINFO_STR_REGISTER + TX0_IOS: sprintf(info->s, "IOS:%X", cpustate->ios); break; |
| 679 | | case CPUINFO_IS_OCTAL: info->i = true; break; |
| 680 | | } |
| 681 | | } |
| 682 | | |
| 683 | | |
| 684 | 440 | /* execute one instruction */ |
| 685 | | static void execute_instruction_64kw(device_t *device) |
| 441 | void tx0_64kw_device::execute_instruction_64kw() |
| 686 | 442 | { |
| 687 | | tx0_state *cpustate = get_safe_token(device); |
| 688 | | |
| 689 | | if (! cpustate->cycle) |
| 443 | if (! m_cycle) |
| 690 | 444 | { |
| 691 | | cpustate->cycle = 1; /* most frequent case */ |
| 445 | m_cycle = 1; /* most frequent case */ |
| 692 | 446 | switch (IR) |
| 693 | 447 | { |
| 694 | 448 | case 0: /* STOre */ |
| r26748 | r26749 | |
| 699 | 453 | if (AC & 0400000) |
| 700 | 454 | { |
| 701 | 455 | PC = MAR & ADDRESS_MASK_64KW; |
| 702 | | cpustate->cycle = 0; /* instruction only takes one cycle if branch |
| 456 | m_cycle = 0; /* instruction only takes one cycle if branch |
| 703 | 457 | is taken */ |
| 704 | 458 | } |
| 705 | 459 | break; |
| r26748 | r26749 | |
| 716 | 470 | if (((MAR & 0030000) >> 12) == 1) |
| 717 | 471 | /* (0.8) IOS In-Out Stop = Stop machine so that an In-Out command |
| 718 | 472 | (specified by digits 6 7 8 of MAR) may be executed */ |
| 719 | | cpustate->ioh = 1; |
| 473 | m_ioh = 1; |
| 720 | 474 | |
| 721 | 475 | if (((MAR & 0007000) >> 9) != 0) |
| 722 | 476 | { |
| r26748 | r26749 | |
| 750 | 504 | /* (5 is undefined) */ |
| 751 | 505 | int index = (MAR & 0007000) >> 9; |
| 752 | 506 | |
| 753 | | if (cpustate->iface->io_handlers[index]) |
| 754 | | (*cpustate->iface->io_handlers[index])(device); |
| 755 | | cpustate->ioh = 1; |
| 507 | call_io_handler(index); |
| 508 | m_ioh = 1; |
| 756 | 509 | } |
| 757 | 510 | break; |
| 758 | 511 | } |
| 759 | 512 | } |
| 760 | 513 | else |
| 761 | 514 | { |
| 762 | | cpustate->cycle = 0; /* always true */ |
| 515 | m_cycle = 0; /* always true */ |
| 763 | 516 | switch (IR) |
| 764 | 517 | { |
| 765 | 518 | case 0: /* STOre */ |
| 766 | | tx0_write(cpustate, MAR, (MBR = AC)); |
| 519 | tx0_write(MAR, (MBR = AC)); |
| 767 | 520 | break; |
| 768 | 521 | |
| 769 | 522 | case 1: /* ADD */ |
| 770 | | MBR = tx0_read(cpustate, MAR); |
| 523 | MBR = tx0_read(MAR); |
| 771 | 524 | |
| 772 | 525 | AC = AC + MBR; |
| 773 | 526 | AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ |
| r26748 | r26749 | |
| 855 | 608 | |
| 856 | 609 | if (((MAR & 0030000) >> 12) == 3) |
| 857 | 610 | /* (1.8) Hlt = Halt the computer */ |
| 858 | | cpustate->run = 0; |
| 611 | m_run = 0; |
| 859 | 612 | |
| 860 | 613 | break; |
| 861 | 614 | } |
| 862 | 615 | } |
| 863 | 616 | } |
| 864 | 617 | |
| 865 | | static void indexed_address_eval(tx0_state *cpustate) |
| 618 | void tx0_device::indexed_address_eval() |
| 866 | 619 | { |
| 867 | 620 | MAR = MAR + XR; |
| 868 | 621 | MAR = (MAR + (MAR >> 14)) & 0037777; /* propagate carry around */ |
| r26748 | r26749 | |
| 873 | 626 | } |
| 874 | 627 | |
| 875 | 628 | /* execute one instruction */ |
| 876 | | static void execute_instruction_8kw(device_t *device) |
| 629 | void tx0_8kw_device::execute_instruction_8kw() |
| 877 | 630 | { |
| 878 | | tx0_state *cpustate = get_safe_token(device); |
| 879 | | |
| 880 | | if (! cpustate->cycle) |
| 631 | if (! m_cycle) |
| 881 | 632 | { |
| 882 | | cpustate->cycle = 1; /* most frequent case */ |
| 633 | m_cycle = 1; /* most frequent case */ |
| 883 | 634 | switch (IR) |
| 884 | 635 | { |
| 885 | 636 | case 0: /* STOre */ |
| r26748 | r26749 | |
| 903 | 654 | if (AC & 0400000) |
| 904 | 655 | { |
| 905 | 656 | PC = MAR & 0017777; |
| 906 | | cpustate->cycle = 0; /* instruction only takes one cycle if branch |
| 657 | m_cycle = 0; /* instruction only takes one cycle if branch |
| 907 | 658 | is taken */ |
| 908 | 659 | } |
| 909 | 660 | break; |
| r26748 | r26749 | |
| 912 | 663 | if ((AC == 0000000) || (AC == 0777777)) |
| 913 | 664 | { |
| 914 | 665 | PC = MAR & 0017777; |
| 915 | | cpustate->cycle = 0; /* instruction only takes one cycle if branch |
| 666 | m_cycle = 0; /* instruction only takes one cycle if branch |
| 916 | 667 | is taken */ |
| 917 | 668 | } |
| 918 | 669 | break; |
| r26748 | r26749 | |
| 920 | 671 | case 18: /* Transfer and Set indeX */ |
| 921 | 672 | XR = PC; |
| 922 | 673 | PC = MAR & 0017777; |
| 923 | | cpustate->cycle = 0; /* instruction only takes one cycle if branch |
| 674 | m_cycle = 0; /* instruction only takes one cycle if branch |
| 924 | 675 | is taken */ |
| 925 | 676 | break; |
| 926 | 677 | |
| r26748 | r26749 | |
| 932 | 683 | else |
| 933 | 684 | XR--; |
| 934 | 685 | PC = MAR & 0017777; |
| 935 | | cpustate->cycle = 0; /* instruction only takes one cycle if branch |
| 686 | m_cycle = 0; /* instruction only takes one cycle if branch |
| 936 | 687 | is taken */ |
| 937 | 688 | } |
| 938 | 689 | break; |
| 939 | 690 | |
| 940 | 691 | case 21: /* TRansfer indeXed */ |
| 941 | | indexed_address_eval(cpustate); |
| 692 | indexed_address_eval(); |
| 942 | 693 | case 20: /* TRAnsfer */ |
| 943 | 694 | PC = MAR & 0017777; |
| 944 | | cpustate->cycle = 0; /* instruction only takes one cycle if branch |
| 695 | m_cycle = 0; /* instruction only takes one cycle if branch |
| 945 | 696 | is taken */ |
| 946 | 697 | break; |
| 947 | 698 | |
| r26748 | r26749 | |
| 949 | 700 | /*if (...) |
| 950 | 701 | { |
| 951 | 702 | PC = MAR & 0017777; |
| 952 | | cpustate->cycle = 0;*/ /* instruction only takes one cycle if branch |
| 703 | m_cycle = 0;*/ /* instruction only takes one cycle if branch |
| 953 | 704 | is taken */ |
| 954 | 705 | /*}*/ |
| 955 | 706 | break; |
| r26748 | r26749 | |
| 969 | 720 | AC = 0; |
| 970 | 721 | |
| 971 | 722 | /* (IOS???) SEL = SELect */ |
| 972 | | if (cpustate->iface->sel_handler) |
| 973 | | (*cpustate->iface->sel_handler)(device); |
| 723 | m_sel_handler(ASSERT_LINE); |
| 974 | 724 | } |
| 975 | 725 | else |
| 976 | 726 | { /* Normal operate class instruction */ |
| r26748 | r26749 | |
| 1020 | 770 | /* (5 is undefined) */ |
| 1021 | 771 | int index = (MAR & 0007000) >> 9; |
| 1022 | 772 | |
| 1023 | | if (cpustate->iface->io_handlers[index]) |
| 1024 | | (*cpustate->iface->io_handlers[index])(device); |
| 1025 | | cpustate->ioh = 1; |
| 773 | call_io_handler(index); |
| 774 | m_ioh = 1; |
| 1026 | 775 | } |
| 1027 | 776 | |
| 1028 | 777 | if (((IR & 001) == 00) && ((MAR & 010000) == 010000)) |
| r26748 | r26749 | |
| 1038 | 787 | } |
| 1039 | 788 | else |
| 1040 | 789 | { |
| 1041 | | if (((IR != 2) && (IR != 3)) || (cpustate->cycle == 2)) |
| 1042 | | cpustate->cycle = 0; |
| 790 | if (((IR != 2) && (IR != 3)) || (m_cycle == 2)) |
| 791 | m_cycle = 0; |
| 1043 | 792 | else |
| 1044 | | cpustate->cycle = 2; /* SXA and ADO have an extra cycle 2 */ |
| 793 | m_cycle = 2; /* SXA and ADO have an extra cycle 2 */ |
| 1045 | 794 | switch (IR) |
| 1046 | 795 | { |
| 1047 | 796 | case 1: /* STore indeXed */ |
| 1048 | | indexed_address_eval(cpustate); |
| 797 | indexed_address_eval(); |
| 1049 | 798 | case 0: /* STOre */ |
| 1050 | | tx0_write(cpustate, MAR, (MBR = AC)); |
| 799 | tx0_write(MAR, (MBR = AC)); |
| 1051 | 800 | break; |
| 1052 | 801 | |
| 1053 | 802 | case 2: /* Store indeX in Address */ |
| 1054 | | if (cpustate->cycle) |
| 803 | if (m_cycle) |
| 1055 | 804 | { /* cycle 1 */ |
| 1056 | | MBR = tx0_read(cpustate, MAR); |
| 805 | MBR = tx0_read(MAR); |
| 1057 | 806 | MBR = (MBR & 0760000) | (XR & 0017777); |
| 1058 | 807 | } |
| 1059 | 808 | else |
| 1060 | 809 | { /* cycle 2 */ |
| 1061 | | tx0_write(cpustate, MAR, MBR); |
| 810 | tx0_write(MAR, MBR); |
| 1062 | 811 | } |
| 1063 | 812 | break; |
| 1064 | 813 | |
| 1065 | 814 | case 3: /* ADd One */ |
| 1066 | | if (cpustate->cycle) |
| 815 | if (m_cycle) |
| 1067 | 816 | { /* cycle 1 */ |
| 1068 | | AC = tx0_read(cpustate, MAR) + 1; |
| 817 | AC = tx0_read(MAR) + 1; |
| 1069 | 818 | |
| 1070 | 819 | #if 0 |
| 1071 | 820 | AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ |
| r26748 | r26749 | |
| 1078 | 827 | } |
| 1079 | 828 | else |
| 1080 | 829 | { /* cycle 2 */ |
| 1081 | | tx0_write(cpustate, MAR, (MBR = AC)); |
| 830 | tx0_write(MAR, (MBR = AC)); |
| 1082 | 831 | } |
| 1083 | 832 | break; |
| 1084 | 833 | |
| 1085 | 834 | case 5: /* Store Lr indeXed */ |
| 1086 | | indexed_address_eval(cpustate); |
| 835 | indexed_address_eval(); |
| 1087 | 836 | case 4: /* Store LR */ |
| 1088 | | tx0_write(cpustate, MAR, (MBR = LR)); |
| 837 | tx0_write(MAR, (MBR = LR)); |
| 1089 | 838 | break; |
| 1090 | 839 | |
| 1091 | 840 | case 6: /* STore Zero */ |
| 1092 | | tx0_write(cpustate, MAR, (MBR = 0)); |
| 841 | tx0_write(MAR, (MBR = 0)); |
| 1093 | 842 | break; |
| 1094 | 843 | |
| 1095 | 844 | case 9: /* ADd indeXed */ |
| 1096 | | indexed_address_eval(cpustate); |
| 845 | indexed_address_eval(); |
| 1097 | 846 | case 8: /* ADD */ |
| 1098 | | MBR = tx0_read(cpustate, MAR); |
| 847 | MBR = tx0_read(MAR); |
| 1099 | 848 | |
| 1100 | 849 | AC = AC + MBR; |
| 1101 | 850 | AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */ |
| r26748 | r26749 | |
| 1105 | 854 | break; |
| 1106 | 855 | |
| 1107 | 856 | case 10: /* LoaD indeX */ |
| 1108 | | MBR = tx0_read(cpustate, MAR); |
| 857 | MBR = tx0_read(MAR); |
| 1109 | 858 | XR = (MBR & 0017777) | ((MBR >> 4) & 0020000); |
| 1110 | 859 | break; |
| 1111 | 860 | |
| 1112 | 861 | case 11: /* AUgment indeX */ |
| 1113 | | MBR = tx0_read(cpustate, MAR); |
| 862 | MBR = tx0_read(MAR); |
| 1114 | 863 | |
| 1115 | 864 | XR = XR + ((MBR & 0017777) | ((MBR >> 4) & 0020000)); |
| 1116 | 865 | XR = (XR + (XR >> 14)) & 0037777; /* propagate carry around */ |
| r26748 | r26749 | |
| 1120 | 869 | break; |
| 1121 | 870 | |
| 1122 | 871 | case 13: /* Load Lr indeXed */ |
| 1123 | | indexed_address_eval(cpustate); |
| 872 | indexed_address_eval(); |
| 1124 | 873 | case 12: /* Load LR */ |
| 1125 | | LR = MBR = tx0_read(cpustate, MAR); |
| 874 | LR = MBR = tx0_read(MAR); |
| 1126 | 875 | break; |
| 1127 | 876 | |
| 1128 | 877 | case 15: /* Load Ac indeXed */ |
| 1129 | | indexed_address_eval(cpustate); |
| 878 | indexed_address_eval(); |
| 1130 | 879 | case 14: /* LoaD Ac */ |
| 1131 | | AC = MBR = tx0_read(cpustate, MAR); |
| 880 | AC = MBR = tx0_read(MAR); |
| 1132 | 881 | break; |
| 1133 | 882 | |
| 1134 | 883 | case 16: /* TRansfer on Negative */ |
| r26748 | r26749 | |
| 1163 | 912 | |
| 1164 | 913 | if (((IR & 001) == 00) && ((MAR & 017000) == 001000)) |
| 1165 | 914 | /* (1.1) TAC = transfer TAC into ac (inclusive or) */ |
| 1166 | | AC |= cpustate->tac; |
| 915 | AC |= m_tac; |
| 1167 | 916 | |
| 1168 | 917 | if (((IR & 001) == 00) && ((MAR & 017000) == 002000)) |
| 1169 | 918 | /* (1.2) TBR = transfer TBR into mbr (inclusive or) */ |
| 1170 | | MBR |= cpustate->tbr; |
| 919 | MBR |= m_tbr; |
| 1171 | 920 | |
| 1172 | 921 | if (((IR & 001) == 00) && ((MAR & 017000) == 006000)) |
| 1173 | 922 | /* (1.2) RPF = Read Program Flag register into mbr (inclusive or) */ |
| r26748 | r26749 | |
| 1263 | 1012 | |
| 1264 | 1013 | if (((IR & 001) == 01) && ((MAR & 017000) == 010000)) |
| 1265 | 1014 | /* (1.8) HLT = HaLT the computer and sound chime */ |
| 1266 | | cpustate->run = 0; |
| 1015 | m_run = 0; |
| 1267 | 1016 | } |
| 1268 | 1017 | break; |
| 1269 | 1018 | |
| r26748 | r26749 | |
| 1279 | 1028 | reset most registers and flip-flops, and initialize a few emulator state |
| 1280 | 1029 | variables. |
| 1281 | 1030 | */ |
| 1282 | | static void pulse_reset(device_t *device) |
| 1031 | void tx0_device::pulse_reset() |
| 1283 | 1032 | { |
| 1284 | | tx0_state *cpustate = get_safe_token(device); |
| 1285 | | |
| 1286 | 1033 | /* processor registers */ |
| 1287 | 1034 | PC = 0; /* ??? */ |
| 1288 | 1035 | IR = 0; /* ??? */ |
| r26748 | r26749 | |
| 1292 | 1039 | /*LR = 0;*/ /* ??? */ |
| 1293 | 1040 | |
| 1294 | 1041 | /* processor state flip-flops */ |
| 1295 | | cpustate->run = 0; /* ??? */ |
| 1296 | | cpustate->rim = 0; /* ??? */ |
| 1297 | | cpustate->ioh = 0; /* ??? */ |
| 1298 | | cpustate->ios = 0; /* ??? */ |
| 1042 | m_run = 0; /* ??? */ |
| 1043 | m_rim = 0; /* ??? */ |
| 1044 | m_ioh = 0; /* ??? */ |
| 1045 | m_ios = 0; /* ??? */ |
| 1299 | 1046 | |
| 1300 | | cpustate->rim_step = 0; |
| 1047 | m_rim_step = 0; |
| 1301 | 1048 | |
| 1302 | 1049 | /* now, we kindly ask IO devices to reset, too */ |
| 1303 | | if (cpustate->iface->io_reset_callback) |
| 1304 | | (*cpustate->iface->io_reset_callback)(device); |
| 1050 | m_io_reset_callback(ASSERT_LINE); |
| 1305 | 1051 | } |
| 1306 | 1052 | |
| 1307 | | DEFINE_LEGACY_CPU_DEVICE(TX0_64KW, tx0_64kw); |
| 1308 | | DEFINE_LEGACY_CPU_DEVICE(TX0_8KW, tx0_8kw); |
| 1053 | void tx0_device::io_complete() |
| 1054 | { |
| 1055 | m_ios = 1; |
| 1056 | } |
| 1057 | |
| 1058 | |
| 1059 | offs_t tx0_8kw_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 1060 | { |
| 1061 | extern CPU_DISASSEMBLE( tx0_8kw ); |
| 1062 | return CPU_DISASSEMBLE_NAME(tx0_8kw)(this, buffer, pc, oprom, opram, options); |
| 1063 | } |
| 1064 | |
| 1065 | |
| 1066 | offs_t tx0_64kw_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 1067 | { |
| 1068 | extern CPU_DISASSEMBLE( tx0_64kw ); |
| 1069 | return CPU_DISASSEMBLE_NAME(tx0_64kw)(this, buffer, pc, oprom, opram, options); |
| 1070 | } |
| 1071 | |
trunk/src/mess/drivers/tx0.c
| r26748 | r26749 | |
| 301 | 301 | colortable_entry_set_value(machine().colortable, total_colors_needed + i, tx0_palette[i]); |
| 302 | 302 | } |
| 303 | 303 | |
| 304 | | static void tx0_io_cpy(device_t *device); |
| 305 | | static void tx0_io_r1l(device_t *device); |
| 306 | | static void tx0_io_r3l(device_t *device); |
| 307 | | static void tx0_io_p6h(device_t *device); |
| 308 | | static void tx0_io_p7h(device_t *device); |
| 309 | | static void tx0_io_prt(device_t *device); |
| 310 | | static void tx0_io_dis(device_t *device); |
| 311 | | static void tx0_sel(device_t *device); |
| 312 | | static void tx0_io_reset_callback(device_t *device); |
| 313 | 304 | |
| 314 | | static const tx0_reset_param_t tx0_reset_param = |
| 315 | | { |
| 316 | | { |
| 317 | | tx0_io_cpy, |
| 318 | | tx0_io_r1l, |
| 319 | | tx0_io_dis, |
| 320 | | tx0_io_r3l, |
| 321 | | tx0_io_prt, |
| 322 | | /*tx0_io_typ*/NULL, |
| 323 | | tx0_io_p6h, |
| 324 | | tx0_io_p7h |
| 325 | | }, |
| 326 | | tx0_sel, |
| 327 | | tx0_io_reset_callback |
| 328 | | }; |
| 329 | | |
| 330 | 305 | static const crt_interface tx0_crt_interface = |
| 331 | 306 | { |
| 332 | 307 | pen_crt_num_levels, |
| r26748 | r26749 | |
| 705 | 680 | /* |
| 706 | 681 | Initiate read of a 6-bit word from tape |
| 707 | 682 | */ |
| 708 | | static void tx0_io_r1l(device_t *device) |
| 683 | WRITE_LINE_MEMBER( tx0_state::tx0_io_r1l ) |
| 709 | 684 | { |
| 710 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 711 | | state->begin_tape_read( 0); |
| 685 | begin_tape_read( 0); |
| 712 | 686 | } |
| 713 | 687 | |
| 714 | 688 | /* |
| 715 | 689 | Initiate read of a 18-bit word from tape (used in read-in mode) |
| 716 | 690 | */ |
| 717 | | static void tx0_io_r3l(device_t *device) |
| 691 | WRITE_LINE_MEMBER( tx0_state::tx0_io_r3l ) |
| 718 | 692 | { |
| 719 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 720 | | state->begin_tape_read(1); |
| 693 | begin_tape_read(1); |
| 721 | 694 | } |
| 722 | 695 | |
| 723 | 696 | /* |
| 724 | 697 | Write a 7-bit word to tape (7th bit clear) |
| 725 | 698 | */ |
| 726 | | static void tx0_io_p6h(device_t *device) |
| 699 | WRITE_LINE_MEMBER( tx0_state::tx0_io_p6h ) |
| 727 | 700 | { |
| 728 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 729 | 701 | int ac; |
| 730 | 702 | |
| 731 | 703 | /* read current AC */ |
| 732 | | ac = device->state().state_int(TX0_AC); |
| 704 | ac = m_maincpu->state_int(TX0_AC); |
| 733 | 705 | /* shuffle and punch 6-bit word */ |
| 734 | | state->tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5)); |
| 706 | tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5)); |
| 735 | 707 | |
| 736 | | state->m_tape_puncher.timer->adjust(attotime::from_usec(15800)); |
| 708 | m_tape_puncher.timer->adjust(attotime::from_usec(15800)); |
| 737 | 709 | } |
| 738 | 710 | |
| 739 | 711 | /* |
| 740 | 712 | Write a 7-bit word to tape (7th bit set) |
| 741 | 713 | */ |
| 742 | | static void tx0_io_p7h(device_t *device) |
| 714 | WRITE_LINE_MEMBER( tx0_state::tx0_io_p7h ) |
| 743 | 715 | { |
| 744 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 745 | 716 | int ac; |
| 746 | 717 | |
| 747 | 718 | /* read current AC */ |
| 748 | | ac = device->state().state_int(TX0_AC); |
| 719 | ac = m_maincpu->state_int(TX0_AC); |
| 749 | 720 | /* shuffle and punch 6-bit word */ |
| 750 | | state->tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5) | 0100); |
| 721 | tape_write(((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5) | 0100); |
| 751 | 722 | |
| 752 | | state->m_tape_puncher.timer->adjust(attotime::from_usec(15800)); |
| 723 | m_tape_puncher.timer->adjust(attotime::from_usec(15800)); |
| 753 | 724 | } |
| 754 | 725 | |
| 755 | 726 | |
| r26748 | r26749 | |
| 793 | 764 | */ |
| 794 | 765 | TIMER_CALLBACK_MEMBER(tx0_state::prt_callback) |
| 795 | 766 | { |
| 796 | | m_maincpu->set_state_int(TX0_IOS,1); |
| 767 | m_maincpu->io_complete(); |
| 797 | 768 | } |
| 798 | 769 | |
| 799 | 770 | /* |
| 800 | 771 | prt io callback |
| 801 | 772 | */ |
| 802 | | static void tx0_io_prt(device_t *device) |
| 773 | WRITE_LINE_MEMBER( tx0_state::tx0_io_prt ) |
| 803 | 774 | { |
| 804 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 805 | 775 | int ac; |
| 806 | 776 | int ch; |
| 807 | 777 | |
| 808 | 778 | /* read current AC */ |
| 809 | | ac = device->state().state_int(TX0_AC); |
| 779 | ac = m_maincpu->state_int(TX0_AC); |
| 810 | 780 | /* shuffle and print 6-bit word */ |
| 811 | 781 | ch = ((ac & 0100000) >> 15) | ((ac & 0010000) >> 11) | ((ac & 0001000) >> 7) | ((ac & 0000100) >> 3) | ((ac & 0000010) << 1) | ((ac & 0000001) << 5); |
| 812 | | state->typewriter_out(ch); |
| 782 | typewriter_out(ch); |
| 813 | 783 | |
| 814 | | state->m_typewriter.prt_timer->adjust(attotime::from_msec(100)); |
| 784 | m_typewriter.prt_timer->adjust(attotime::from_msec(100)); |
| 815 | 785 | } |
| 816 | 786 | |
| 817 | 787 | |
| r26748 | r26749 | |
| 820 | 790 | */ |
| 821 | 791 | TIMER_CALLBACK_MEMBER(tx0_state::dis_callback) |
| 822 | 792 | { |
| 823 | | m_maincpu->set_state_int(TX0_IOS,1); |
| 793 | m_maincpu->io_complete(); |
| 824 | 794 | } |
| 825 | 795 | |
| 826 | 796 | /* |
| 827 | 797 | Plot one point on crt |
| 828 | 798 | */ |
| 829 | | static void tx0_io_dis(device_t *device) |
| 799 | WRITE_LINE_MEMBER( tx0_state::tx0_io_dis ) |
| 830 | 800 | { |
| 831 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 832 | 801 | int ac; |
| 833 | 802 | int x; |
| 834 | 803 | int y; |
| 835 | 804 | |
| 836 | | ac = device->state().state_int(TX0_AC); |
| 805 | ac = m_maincpu->state_int(TX0_AC); |
| 837 | 806 | x = ac >> 9; |
| 838 | 807 | y = ac & 0777; |
| 839 | | state->tx0_plot(x, y); |
| 808 | tx0_plot(x, y); |
| 840 | 809 | |
| 841 | | state->m_dis_timer->adjust(attotime::from_usec(50)); |
| 810 | m_dis_timer->adjust(attotime::from_usec(50)); |
| 842 | 811 | } |
| 843 | 812 | |
| 844 | 813 | |
| r26748 | r26749 | |
| 944 | 913 | } |
| 945 | 914 | } |
| 946 | 915 | |
| 947 | | static void magtape_callback(device_t *device) |
| 916 | void tx0_state::magtape_callback() |
| 948 | 917 | { |
| 949 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 950 | 918 | UINT8 buf = 0; |
| 951 | 919 | int lr; |
| 952 | 920 | |
| 953 | | switch (state->m_magtape.state) |
| 921 | switch (m_magtape.state) |
| 954 | 922 | { |
| 955 | 923 | case MTS_UNSELECTING: |
| 956 | | state->m_magtape.state = MTS_UNSELECTED; |
| 924 | m_magtape.state = MTS_UNSELECTED; |
| 957 | 925 | |
| 958 | 926 | case MTS_UNSELECTED: |
| 959 | | if (state->m_magtape.sel_pending) |
| 927 | if (m_magtape.sel_pending) |
| 960 | 928 | { |
| 961 | 929 | int mar; |
| 962 | 930 | |
| 963 | | mar = device->state().state_int(TX0_MAR); |
| 931 | mar = m_maincpu->state_int(TX0_MAR); |
| 964 | 932 | |
| 965 | 933 | if ((mar & 03) != 1) |
| 966 | 934 | { /* unimplemented device: remain in unselected state and set rwc |
| 967 | 935 | flag? */ |
| 968 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_RWC); |
| 936 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_RWC); |
| 969 | 937 | } |
| 970 | 938 | else |
| 971 | 939 | { |
| 972 | | state->m_magtape.state = MTS_SELECTING; |
| 940 | m_magtape.state = MTS_SELECTING; |
| 973 | 941 | |
| 974 | | state->m_magtape.command = (mar & 014 >> 2); |
| 942 | m_magtape.command = (mar & 014 >> 2); |
| 975 | 943 | |
| 976 | | state->m_magtape.binary_flag = (mar & 020 >> 4); |
| 944 | m_magtape.binary_flag = (mar & 020 >> 4); |
| 977 | 945 | |
| 978 | | if (state->m_magtape.img) |
| 979 | | state->schedule_select(); |
| 946 | if (m_magtape.img) |
| 947 | schedule_select(); |
| 980 | 948 | } |
| 981 | 949 | |
| 982 | | state->m_magtape.sel_pending = FALSE; |
| 983 | | device->state().set_state_int(TX0_IOS,1); |
| 950 | m_magtape.sel_pending = FALSE; |
| 951 | m_maincpu->io_complete(); |
| 984 | 952 | } |
| 985 | 953 | break; |
| 986 | 954 | |
| 987 | 955 | case MTS_SELECTING: |
| 988 | | state->m_magtape.state = MTS_SELECTED; |
| 989 | | switch (state->m_magtape.command) |
| 956 | m_magtape.state = MTS_SELECTED; |
| 957 | switch (m_magtape.command) |
| 990 | 958 | { |
| 991 | 959 | case 0: /* backspace */ |
| 992 | | state->m_magtape.long_parity = 0177; |
| 993 | | state->m_magtape.u.backspace_state = MTBSS_STATE0; |
| 960 | m_magtape.long_parity = 0177; |
| 961 | m_magtape.u.backspace_state = MTBSS_STATE0; |
| 994 | 962 | break; |
| 995 | 963 | case 1: /* read */ |
| 996 | | state->m_magtape.long_parity = 0177; |
| 997 | | state->m_magtape.u.read.state = MTRDS_STATE0; |
| 964 | m_magtape.long_parity = 0177; |
| 965 | m_magtape.u.read.state = MTRDS_STATE0; |
| 998 | 966 | break; |
| 999 | 967 | case 2: /* rewind */ |
| 1000 | 968 | break; |
| 1001 | 969 | case 3: /* write */ |
| 1002 | | state->m_magtape.long_parity = 0177; |
| 1003 | | state->m_magtape.u.write.state = MTWTS_STATE0; |
| 1004 | | switch (state->m_magtape.irg_pos) |
| 970 | m_magtape.long_parity = 0177; |
| 971 | m_magtape.u.write.state = MTWTS_STATE0; |
| 972 | switch (m_magtape.irg_pos) |
| 1005 | 973 | { |
| 1006 | 974 | case MTIRGP_START: |
| 1007 | | state->m_magtape.u.write.counter = 150; |
| 975 | m_magtape.u.write.counter = 150; |
| 1008 | 976 | break; |
| 1009 | 977 | case MTIRGP_ENDMINUS1: |
| 1010 | | state->m_magtape.u.write.counter = 1; |
| 978 | m_magtape.u.write.counter = 1; |
| 1011 | 979 | break; |
| 1012 | 980 | case MTIRGP_END: |
| 1013 | | state->m_magtape.u.write.counter = 0; |
| 981 | m_magtape.u.write.counter = 0; |
| 1014 | 982 | break; |
| 1015 | 983 | } |
| 1016 | 984 | break; |
| 1017 | 985 | } |
| 1018 | 986 | |
| 1019 | 987 | case MTS_SELECTED: |
| 1020 | | switch (state->m_magtape.command) |
| 988 | switch (m_magtape.command) |
| 1021 | 989 | { |
| 1022 | 990 | case 0: /* backspace */ |
| 1023 | | if (state->m_magtape.img->ftell() == 0) |
| 991 | if (m_magtape.img->ftell() == 0) |
| 1024 | 992 | { /* tape at ldp */ |
| 1025 | | state->m_magtape.state = MTS_UNSELECTING; |
| 1026 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_RWC); |
| 1027 | | state->schedule_unselect(); |
| 993 | m_magtape.state = MTS_UNSELECTING; |
| 994 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_RWC); |
| 995 | schedule_unselect(); |
| 1028 | 996 | } |
| 1029 | | else if (state->m_magtape.img->fseek( -1, SEEK_CUR)) |
| 997 | else if (m_magtape.img->fseek( -1, SEEK_CUR)) |
| 1030 | 998 | { /* eject tape */ |
| 1031 | | state->m_magtape.img->unload(); |
| 999 | m_magtape.img->unload(); |
| 1032 | 1000 | } |
| 1033 | | else if (state->m_magtape.img->fread(&buf, 1) != 1) |
| 1001 | else if (m_magtape.img->fread(&buf, 1) != 1) |
| 1034 | 1002 | { /* eject tape */ |
| 1035 | | state->m_magtape.img->unload(); |
| 1003 | m_magtape.img->unload(); |
| 1036 | 1004 | } |
| 1037 | | else if (state->m_magtape.img->fseek( -1, SEEK_CUR)) |
| 1005 | else if (m_magtape.img->fseek( -1, SEEK_CUR)) |
| 1038 | 1006 | { /* eject tape */ |
| 1039 | | state->m_magtape.img->unload(); |
| 1007 | m_magtape.img->unload(); |
| 1040 | 1008 | } |
| 1041 | 1009 | else |
| 1042 | 1010 | { |
| 1043 | 1011 | buf &= 0x7f; /* 7-bit tape, ignore 8th bit */ |
| 1044 | | state->m_magtape.long_parity ^= buf; |
| 1045 | | switch (state->m_magtape.u.backspace_state) |
| 1012 | m_magtape.long_parity ^= buf; |
| 1013 | switch (m_magtape.u.backspace_state) |
| 1046 | 1014 | { |
| 1047 | 1015 | case MTBSS_STATE0: |
| 1048 | 1016 | /* STATE0 -> initial interrecord gap, longitudinal parity; |
| 1049 | 1017 | if longitudinal parity was all 0s, gap between longitudinal |
| 1050 | 1018 | parity and data, first byte of data */ |
| 1051 | 1019 | if (buf != 0) |
| 1052 | | state->m_magtape.u.backspace_state = MTBSS_STATE1; |
| 1020 | m_magtape.u.backspace_state = MTBSS_STATE1; |
| 1053 | 1021 | break; |
| 1054 | 1022 | case MTBSS_STATE1: |
| 1055 | 1023 | /* STATE1 -> first byte of gap between longitudinal parity and |
| 1056 | 1024 | data, second byte of data */ |
| 1057 | 1025 | if (buf == 0) |
| 1058 | | state->m_magtape.u.backspace_state = MTBSS_STATE2; |
| 1026 | m_magtape.u.backspace_state = MTBSS_STATE2; |
| 1059 | 1027 | else |
| 1060 | | state->m_magtape.u.backspace_state = MTBSS_STATE5; |
| 1028 | m_magtape.u.backspace_state = MTBSS_STATE5; |
| 1061 | 1029 | break; |
| 1062 | 1030 | case MTBSS_STATE2: |
| 1063 | 1031 | /* STATE2 -> second byte of gap between longitudinal parity and |
| 1064 | 1032 | data */ |
| 1065 | 1033 | if (buf == 0) |
| 1066 | | state->m_magtape.u.backspace_state = MTBSS_STATE3; |
| 1034 | m_magtape.u.backspace_state = MTBSS_STATE3; |
| 1067 | 1035 | else |
| 1068 | 1036 | { |
| 1069 | 1037 | logerror("tape seems to be corrupt\n"); |
| 1070 | 1038 | /* eject tape */ |
| 1071 | | state->m_magtape.img->unload(); |
| 1039 | m_magtape.img->unload(); |
| 1072 | 1040 | } |
| 1073 | 1041 | break; |
| 1074 | 1042 | case MTBSS_STATE3: |
| 1075 | 1043 | /* STATE3 -> third byte of gap between longitudinal parity and |
| 1076 | 1044 | data */ |
| 1077 | 1045 | if (buf == 0) |
| 1078 | | state->m_magtape.u.backspace_state = MTBSS_STATE4; |
| 1046 | m_magtape.u.backspace_state = MTBSS_STATE4; |
| 1079 | 1047 | else |
| 1080 | 1048 | { |
| 1081 | 1049 | logerror("tape seems to be corrupt\n"); |
| 1082 | 1050 | /* eject tape */ |
| 1083 | | state->m_magtape.img->unload(); |
| 1051 | m_magtape.img->unload(); |
| 1084 | 1052 | } |
| 1085 | 1053 | break; |
| 1086 | 1054 | case MTBSS_STATE4: |
| r26748 | r26749 | |
| 1088 | 1056 | interrecord gap after data */ |
| 1089 | 1057 | if (buf == 0) |
| 1090 | 1058 | { |
| 1091 | | if (state->m_magtape.long_parity) |
| 1059 | if (m_magtape.long_parity) |
| 1092 | 1060 | logerror("invalid longitudinal parity\n"); |
| 1093 | 1061 | /* set EOR and unselect... */ |
| 1094 | | state->m_magtape.state = MTS_UNSELECTING; |
| 1095 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_EOR); |
| 1096 | | state->schedule_unselect(); |
| 1097 | | state->m_magtape.irg_pos = MTIRGP_ENDMINUS1; |
| 1062 | m_magtape.state = MTS_UNSELECTING; |
| 1063 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_EOR); |
| 1064 | schedule_unselect(); |
| 1065 | m_magtape.irg_pos = MTIRGP_ENDMINUS1; |
| 1098 | 1066 | } |
| 1099 | 1067 | else |
| 1100 | | state->m_magtape.u.backspace_state = MTBSS_STATE5; |
| 1068 | m_magtape.u.backspace_state = MTBSS_STATE5; |
| 1101 | 1069 | break; |
| 1102 | 1070 | case MTBSS_STATE5: |
| 1103 | 1071 | /* STATE5 -> second byte of data word */ |
| r26748 | r26749 | |
| 1105 | 1073 | { |
| 1106 | 1074 | logerror("tape seems to be corrupt\n"); |
| 1107 | 1075 | /* eject tape */ |
| 1108 | | state->m_magtape.img->unload(); |
| 1076 | m_magtape.img->unload(); |
| 1109 | 1077 | } |
| 1110 | 1078 | else |
| 1111 | | state->m_magtape.u.backspace_state = MTBSS_STATE6; |
| 1079 | m_magtape.u.backspace_state = MTBSS_STATE6; |
| 1112 | 1080 | break; |
| 1113 | 1081 | case MTBSS_STATE6: |
| 1114 | 1082 | /* STATE6 -> third byte of data word */ |
| r26748 | r26749 | |
| 1116 | 1084 | { |
| 1117 | 1085 | logerror("tape seems to be corrupt\n"); |
| 1118 | 1086 | /* eject tape */ |
| 1119 | | state->m_magtape.img->unload(); |
| 1087 | m_magtape.img->unload(); |
| 1120 | 1088 | } |
| 1121 | 1089 | else |
| 1122 | | state->m_magtape.u.backspace_state = MTBSS_STATE6; |
| 1090 | m_magtape.u.backspace_state = MTBSS_STATE6; |
| 1123 | 1091 | break; |
| 1124 | 1092 | } |
| 1125 | | if (state->m_magtape.state != MTS_UNSELECTING) |
| 1126 | | state->m_magtape.timer->adjust(attotime::from_usec(66)); |
| 1093 | if (m_magtape.state != MTS_UNSELECTING) |
| 1094 | m_magtape.timer->adjust(attotime::from_usec(66)); |
| 1127 | 1095 | } |
| 1128 | 1096 | break; |
| 1129 | 1097 | |
| 1130 | 1098 | case 1: /* read */ |
| 1131 | | if (state->m_magtape.img->fread(&buf, 1) != 1) |
| 1099 | if (m_magtape.img->fread(&buf, 1) != 1) |
| 1132 | 1100 | { /* I/O error or EOF? */ |
| 1133 | 1101 | /* The MAME fileio layer makes it very hard to make the |
| 1134 | 1102 | difference... MAME seems to assume that I/O errors never |
| 1135 | 1103 | happen, whereas it is really easy to cause one by |
| 1136 | 1104 | deconnecting an external drive the image is located on!!! */ |
| 1137 | 1105 | UINT64 offs; |
| 1138 | | offs = state->m_magtape.img->ftell(); |
| 1139 | | if (state->m_magtape.img->fseek( 0, SEEK_END) || (offs != state->m_magtape.img->ftell())) |
| 1106 | offs = m_magtape.img->ftell(); |
| 1107 | if (m_magtape.img->fseek( 0, SEEK_END) || (offs != m_magtape.img->ftell())) |
| 1140 | 1108 | { /* I/O error */ |
| 1141 | 1109 | /* eject tape */ |
| 1142 | | state->m_magtape.img->unload(); |
| 1110 | m_magtape.img->unload(); |
| 1143 | 1111 | } |
| 1144 | 1112 | else |
| 1145 | 1113 | { /* end of tape -> ??? */ |
| 1146 | 1114 | /* maybe we run past end of tape, so that tape is ejected from |
| 1147 | 1115 | upper reel and unit becomes unavailable??? */ |
| 1148 | | /*state->m_magtape.img->unload();*/ |
| 1116 | /*m_magtape.img->unload();*/ |
| 1149 | 1117 | /* Or do we stop at EOT mark??? */ |
| 1150 | | state->m_magtape.state = MTS_UNSELECTING; |
| 1151 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_EOT); |
| 1152 | | state->schedule_unselect(); |
| 1118 | m_magtape.state = MTS_UNSELECTING; |
| 1119 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_EOT); |
| 1120 | schedule_unselect(); |
| 1153 | 1121 | } |
| 1154 | 1122 | } |
| 1155 | 1123 | else |
| 1156 | 1124 | { |
| 1157 | 1125 | buf &= 0x7f; /* 7-bit tape, ignore 8th bit */ |
| 1158 | | state->m_magtape.long_parity ^= buf; |
| 1159 | | switch (state->m_magtape.u.read.state) |
| 1126 | m_magtape.long_parity ^= buf; |
| 1127 | switch (m_magtape.u.read.state) |
| 1160 | 1128 | { |
| 1161 | 1129 | case MTRDS_STATE0: |
| 1162 | 1130 | /* STATE0 -> interrecord blank or first byte of data */ |
| 1163 | 1131 | if (buf != 0) |
| 1164 | 1132 | { |
| 1165 | | if (state->m_magtape.cpy_pending) |
| 1133 | if (m_magtape.cpy_pending) |
| 1166 | 1134 | { /* read command */ |
| 1167 | | state->m_magtape.u.read.space_flag = FALSE; |
| 1168 | | device->state().set_state_int(TX0_IOS,1); |
| 1169 | | device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) |
| 1135 | m_magtape.u.read.space_flag = FALSE; |
| 1136 | m_maincpu->set_state_int(TX0_IOS,1); |
| 1137 | m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333) |
| 1170 | 1138 | | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); |
| 1171 | 1139 | /* check parity */ |
| 1172 | | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) |
| 1173 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); |
| 1140 | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag)) |
| 1141 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC); |
| 1174 | 1142 | } |
| 1175 | 1143 | else |
| 1176 | 1144 | { /* space command */ |
| 1177 | | state->m_magtape.u.read.space_flag = TRUE; |
| 1145 | m_magtape.u.read.space_flag = TRUE; |
| 1178 | 1146 | } |
| 1179 | | state->m_magtape.u.read.state = MTRDS_STATE1; |
| 1147 | m_magtape.u.read.state = MTRDS_STATE1; |
| 1180 | 1148 | } |
| 1181 | 1149 | break; |
| 1182 | 1150 | case MTRDS_STATE1: |
| r26748 | r26749 | |
| 1185 | 1153 | { |
| 1186 | 1154 | logerror("tape seems to be corrupt\n"); |
| 1187 | 1155 | /* eject tape */ |
| 1188 | | state->m_magtape.img->unload(); |
| 1156 | m_magtape.img->unload(); |
| 1189 | 1157 | } |
| 1190 | | if (!state->m_magtape.u.read.space_flag) |
| 1158 | if (!m_magtape.u.read.space_flag) |
| 1191 | 1159 | { |
| 1192 | | device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) |
| 1160 | m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333) |
| 1193 | 1161 | | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); |
| 1194 | 1162 | /* check parity */ |
| 1195 | | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) |
| 1196 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); |
| 1163 | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag)) |
| 1164 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC); |
| 1197 | 1165 | } |
| 1198 | | state->m_magtape.u.read.state = MTRDS_STATE2; |
| 1166 | m_magtape.u.read.state = MTRDS_STATE2; |
| 1199 | 1167 | break; |
| 1200 | 1168 | case MTRDS_STATE2: |
| 1201 | 1169 | /* STATE2 -> third byte of data word */ |
| r26748 | r26749 | |
| 1203 | 1171 | { |
| 1204 | 1172 | logerror("tape seems to be corrupt\n"); |
| 1205 | 1173 | /* eject tape */ |
| 1206 | | state->m_magtape.img->unload(); |
| 1174 | m_magtape.img->unload(); |
| 1207 | 1175 | } |
| 1208 | | if (!state->m_magtape.u.read.space_flag) |
| 1176 | if (!m_magtape.u.read.space_flag) |
| 1209 | 1177 | { |
| 1210 | | device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) |
| 1178 | m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333) |
| 1211 | 1179 | | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); |
| 1212 | 1180 | /* check parity */ |
| 1213 | | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) |
| 1214 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); |
| 1181 | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag)) |
| 1182 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC); |
| 1215 | 1183 | /* synchronize with cpy instruction */ |
| 1216 | | if (state->m_magtape.cpy_pending) |
| 1217 | | device->state().set_state_int(TX0_IOS,1); |
| 1184 | if (m_magtape.cpy_pending) |
| 1185 | m_maincpu->set_state_int(TX0_IOS,1); |
| 1218 | 1186 | else |
| 1219 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_RWC); |
| 1187 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_RWC); |
| 1220 | 1188 | } |
| 1221 | | state->m_magtape.u.read.state = MTRDS_STATE3; |
| 1189 | m_magtape.u.read.state = MTRDS_STATE3; |
| 1222 | 1190 | break; |
| 1223 | 1191 | case MTRDS_STATE3: |
| 1224 | 1192 | /* STATE3 -> first byte of new word of data, or first byte |
| 1225 | 1193 | of gap between data and longitudinal parity */ |
| 1226 | 1194 | if (buf != 0) |
| 1227 | 1195 | { |
| 1228 | | state->m_magtape.u.read.state = MTRDS_STATE1; |
| 1229 | | if (!state->m_magtape.u.read.space_flag) |
| 1196 | m_magtape.u.read.state = MTRDS_STATE1; |
| 1197 | if (!m_magtape.u.read.space_flag) |
| 1230 | 1198 | { |
| 1231 | | device->state().set_state_int(TX0_LR, ((device->state().state_int(TX0_LR) >> 1) & 0333333) |
| 1199 | m_maincpu->set_state_int(TX0_LR, ((m_maincpu->state_int(TX0_LR) >> 1) & 0333333) |
| 1232 | 1200 | | ((buf & 040) << 12) | ((buf & 020) << 10) | ((buf & 010) << 8) | ((buf & 004) << 6) | ((buf & 002) << 4) | ((buf & 001) << 2)); |
| 1233 | 1201 | /* check parity */ |
| 1234 | | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ state->m_magtape.binary_flag)) |
| 1235 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); |
| 1202 | if (! (((buf ^ (buf >> 1) ^ (buf >> 2) ^ (buf >> 3) ^ (buf >> 4) ^ (buf >> 5) ^ (buf >> 6) ^ (buf >> 7)) & 1) ^ m_magtape.binary_flag)) |
| 1203 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC); |
| 1236 | 1204 | } |
| 1237 | 1205 | } |
| 1238 | 1206 | else |
| 1239 | | state->m_magtape.u.read.state = MTRDS_STATE4; |
| 1207 | m_magtape.u.read.state = MTRDS_STATE4; |
| 1240 | 1208 | break; |
| 1241 | 1209 | case MTRDS_STATE4: |
| 1242 | 1210 | /* STATE4 -> second byte of gap between data and |
| r26748 | r26749 | |
| 1245 | 1213 | { |
| 1246 | 1214 | logerror("tape seems to be corrupt\n"); |
| 1247 | 1215 | /* eject tape */ |
| 1248 | | state->m_magtape.img->unload(); |
| 1216 | m_magtape.img->unload(); |
| 1249 | 1217 | } |
| 1250 | 1218 | else |
| 1251 | | state->m_magtape.u.read.state = MTRDS_STATE5; |
| 1219 | m_magtape.u.read.state = MTRDS_STATE5; |
| 1252 | 1220 | break; |
| 1253 | 1221 | |
| 1254 | 1222 | case MTRDS_STATE5: |
| r26748 | r26749 | |
| 1258 | 1226 | { |
| 1259 | 1227 | logerror("tape seems to be corrupt\n"); |
| 1260 | 1228 | /* eject tape */ |
| 1261 | | state->m_magtape.img->unload(); |
| 1229 | m_magtape.img->unload(); |
| 1262 | 1230 | } |
| 1263 | 1231 | else |
| 1264 | | state->m_magtape.u.read.state = MTRDS_STATE6; |
| 1232 | m_magtape.u.read.state = MTRDS_STATE6; |
| 1265 | 1233 | break; |
| 1266 | 1234 | |
| 1267 | 1235 | case MTRDS_STATE6: |
| 1268 | 1236 | /* STATE6 -> longitudinal parity */ |
| 1269 | 1237 | /* check parity */ |
| 1270 | | if (state->m_magtape.long_parity) |
| 1238 | if (m_magtape.long_parity) |
| 1271 | 1239 | { |
| 1272 | 1240 | logerror("invalid longitudinal parity\n"); |
| 1273 | 1241 | /* no idea if the original tx-0 magtape controller |
| 1274 | 1242 | checks parity, but can't harm if we do */ |
| 1275 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_PC); |
| 1243 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_PC); |
| 1276 | 1244 | } |
| 1277 | 1245 | /* set EOR and unselect... */ |
| 1278 | | state->m_magtape.state = MTS_UNSELECTING; |
| 1279 | | device->state().set_state_int(TX0_PF, device->state().state_int(TX0_PF) | PF_EOR); |
| 1280 | | state->schedule_unselect(); |
| 1281 | | state->m_magtape.irg_pos = MTIRGP_START; |
| 1246 | m_magtape.state = MTS_UNSELECTING; |
| 1247 | m_maincpu->set_state_int(TX0_PF, m_maincpu->state_int(TX0_PF) | PF_EOR); |
| 1248 | schedule_unselect(); |
| 1249 | m_magtape.irg_pos = MTIRGP_START; |
| 1282 | 1250 | break; |
| 1283 | 1251 | } |
| 1284 | | if (state->m_magtape.state != MTS_UNSELECTING) |
| 1285 | | state->m_magtape.timer->adjust(attotime::from_usec(66)); |
| 1252 | if (m_magtape.state != MTS_UNSELECTING) |
| 1253 | m_magtape.timer->adjust(attotime::from_usec(66)); |
| 1286 | 1254 | } |
| 1287 | 1255 | break; |
| 1288 | 1256 | |
| 1289 | 1257 | case 2: /* rewind */ |
| 1290 | | state->m_magtape.state = MTS_UNSELECTING; |
| 1258 | m_magtape.state = MTS_UNSELECTING; |
| 1291 | 1259 | /* we rewind at 10*read speed (I don't know the real value) */ |
| 1292 | | state->m_magtape.timer->adjust((attotime::from_nsec(6600) * state->m_magtape.img->ftell())); |
| 1260 | m_magtape.timer->adjust((attotime::from_nsec(6600) * m_magtape.img->ftell())); |
| 1293 | 1261 | //schedule_unselect(state); |
| 1294 | | state->m_magtape.img->fseek( 0, SEEK_END); |
| 1295 | | state->m_magtape.irg_pos = MTIRGP_END; |
| 1262 | m_magtape.img->fseek( 0, SEEK_END); |
| 1263 | m_magtape.irg_pos = MTIRGP_END; |
| 1296 | 1264 | break; |
| 1297 | 1265 | |
| 1298 | 1266 | case 3: /* write */ |
| 1299 | | switch (state->m_magtape.u.write.state) |
| 1267 | switch (m_magtape.u.write.state) |
| 1300 | 1268 | { |
| 1301 | 1269 | case MTWTS_STATE0: |
| 1302 | | if (state->m_magtape.u.write.counter != 0) |
| 1270 | if (m_magtape.u.write.counter != 0) |
| 1303 | 1271 | { |
| 1304 | | state->m_magtape.u.write.counter--; |
| 1272 | m_magtape.u.write.counter--; |
| 1305 | 1273 | buf = 0; |
| 1306 | 1274 | break; |
| 1307 | 1275 | } |
| 1308 | 1276 | else |
| 1309 | 1277 | { |
| 1310 | | state->m_magtape.u.write.state = MTWTS_STATE1; |
| 1278 | m_magtape.u.write.state = MTWTS_STATE1; |
| 1311 | 1279 | } |
| 1312 | 1280 | |
| 1313 | 1281 | case MTWTS_STATE1: |
| 1314 | | if (state->m_magtape.u.write.counter) |
| 1282 | if (m_magtape.u.write.counter) |
| 1315 | 1283 | { |
| 1316 | | state->m_magtape.u.write.counter--; |
| 1317 | | lr = device->state().state_int(TX0_LR); |
| 1284 | m_magtape.u.write.counter--; |
| 1285 | lr = m_maincpu->state_int(TX0_LR); |
| 1318 | 1286 | buf = ((lr >> 10) & 040) | ((lr >> 8) & 020) | ((lr >> 6) & 010) | ((lr >> 4) & 004) | ((lr >> 2) & 002) | (lr & 001); |
| 1319 | | buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!state->m_magtape.binary_flag) << 6)) & 0100; |
| 1320 | | device->state().set_state_int(TX0_LR, lr >> 1); |
| 1287 | buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!m_magtape.binary_flag) << 6)) & 0100; |
| 1288 | m_maincpu->set_state_int(TX0_LR, lr >> 1); |
| 1321 | 1289 | } |
| 1322 | 1290 | else |
| 1323 | 1291 | { |
| 1324 | | if (state->m_magtape.cpy_pending) |
| 1292 | if (m_magtape.cpy_pending) |
| 1325 | 1293 | { |
| 1326 | | device->state().set_state_int(TX0_IOS,1); |
| 1327 | | lr = device->state().state_int(TX0_LR); |
| 1294 | m_maincpu->set_state_int(TX0_IOS,1); |
| 1295 | lr = m_maincpu->state_int(TX0_LR); |
| 1328 | 1296 | buf = ((lr >> 10) & 040) | ((lr >> 8) & 020) | ((lr >> 6) & 010) | ((lr >> 4) & 004) | ((lr >> 2) & 002) | (lr & 001); |
| 1329 | | buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!state->m_magtape.binary_flag) << 6)) & 0100; |
| 1330 | | device->state().set_state_int(TX0_LR, lr >> 1); |
| 1331 | | state->m_magtape.u.write.counter = 2; |
| 1297 | buf |= ((buf << 1) ^ (buf << 2) ^ (buf << 3) ^ (buf << 4) ^ (buf << 5) ^ (buf << 6) ^ ((!m_magtape.binary_flag) << 6)) & 0100; |
| 1298 | m_maincpu->set_state_int(TX0_LR, lr >> 1); |
| 1299 | m_magtape.u.write.counter = 2; |
| 1332 | 1300 | break; |
| 1333 | 1301 | } |
| 1334 | 1302 | else |
| 1335 | 1303 | { |
| 1336 | | state->m_magtape.u.write.state = MTWTS_STATE2; |
| 1337 | | state->m_magtape.u.write.counter = 3; |
| 1304 | m_magtape.u.write.state = MTWTS_STATE2; |
| 1305 | m_magtape.u.write.counter = 3; |
| 1338 | 1306 | } |
| 1339 | 1307 | } |
| 1340 | 1308 | |
| 1341 | 1309 | case MTWTS_STATE2: |
| 1342 | | if (state->m_magtape.u.write.counter != 0) |
| 1310 | if (m_magtape.u.write.counter != 0) |
| 1343 | 1311 | { |
| 1344 | | state->m_magtape.u.write.counter--; |
| 1312 | m_magtape.u.write.counter--; |
| 1345 | 1313 | buf = 0; |
| 1346 | 1314 | break; |
| 1347 | 1315 | } |
| 1348 | 1316 | else |
| 1349 | 1317 | { |
| 1350 | | buf = state->m_magtape.long_parity; |
| 1351 | | state->m_magtape.state = (state_t)MTWTS_STATE3; |
| 1352 | | state->m_magtape.u.write.counter = 150; |
| 1318 | buf = m_magtape.long_parity; |
| 1319 | m_magtape.state = (state_t)MTWTS_STATE3; |
| 1320 | m_magtape.u.write.counter = 150; |
| 1353 | 1321 | } |
| 1354 | 1322 | break; |
| 1355 | 1323 | |
| 1356 | 1324 | case MTWTS_STATE3: |
| 1357 | | if (state->m_magtape.u.write.counter != 0) |
| 1325 | if (m_magtape.u.write.counter != 0) |
| 1358 | 1326 | { |
| 1359 | | state->m_magtape.u.write.counter--; |
| 1327 | m_magtape.u.write.counter--; |
| 1360 | 1328 | buf = 0; |
| 1361 | 1329 | break; |
| 1362 | 1330 | } |
| 1363 | 1331 | else |
| 1364 | 1332 | { |
| 1365 | | state->m_magtape.state = MTS_UNSELECTING; |
| 1366 | | state->schedule_unselect(); |
| 1367 | | state->m_magtape.irg_pos = MTIRGP_END; |
| 1333 | m_magtape.state = MTS_UNSELECTING; |
| 1334 | schedule_unselect(); |
| 1335 | m_magtape.irg_pos = MTIRGP_END; |
| 1368 | 1336 | } |
| 1369 | 1337 | break; |
| 1370 | 1338 | } |
| 1371 | | if (state->m_magtape.state != MTS_UNSELECTING) |
| 1339 | if (m_magtape.state != MTS_UNSELECTING) |
| 1372 | 1340 | { /* write data word */ |
| 1373 | | state->m_magtape.long_parity ^= buf; |
| 1374 | | if (state->m_magtape.img->fwrite(&buf, 1) != 1) |
| 1341 | m_magtape.long_parity ^= buf; |
| 1342 | if (m_magtape.img->fwrite(&buf, 1) != 1) |
| 1375 | 1343 | { /* I/O error */ |
| 1376 | 1344 | /* eject tape */ |
| 1377 | | state->m_magtape.img->unload(); |
| 1345 | m_magtape.img->unload(); |
| 1378 | 1346 | } |
| 1379 | 1347 | else |
| 1380 | | state->m_magtape.timer->adjust(attotime::from_usec(66)); |
| 1348 | m_magtape.timer->adjust(attotime::from_usec(66)); |
| 1381 | 1349 | } |
| 1382 | 1350 | break; |
| 1383 | 1351 | } |
| r26748 | r26749 | |
| 1385 | 1353 | } |
| 1386 | 1354 | } |
| 1387 | 1355 | |
| 1388 | | static void tx0_sel(device_t *device) |
| 1356 | WRITE_LINE_MEMBER( tx0_state::tx0_sel ) |
| 1389 | 1357 | { |
| 1390 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 1391 | | state->m_magtape.sel_pending = TRUE; |
| 1358 | m_magtape.sel_pending = TRUE; |
| 1392 | 1359 | |
| 1393 | | if (state->m_magtape.state == MTS_UNSELECTED) |
| 1360 | if (m_magtape.state == MTS_UNSELECTED) |
| 1394 | 1361 | { |
| 1395 | 1362 | if (0) |
| 1396 | | magtape_callback(device); |
| 1397 | | state->m_magtape.timer->adjust(attotime::zero); |
| 1363 | magtape_callback(); |
| 1364 | m_magtape.timer->adjust(attotime::zero); |
| 1398 | 1365 | } |
| 1399 | 1366 | } |
| 1400 | 1367 | |
| 1401 | | static void tx0_io_cpy(device_t *device) |
| 1368 | WRITE_LINE_MEMBER( tx0_state::tx0_io_cpy ) |
| 1402 | 1369 | { |
| 1403 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 1404 | | switch (state->m_magtape.state) |
| 1370 | switch (m_magtape.state) |
| 1405 | 1371 | { |
| 1406 | 1372 | case MTS_UNSELECTED: |
| 1407 | 1373 | case MTS_UNSELECTING: |
| 1408 | 1374 | /* ignore instruction and set rwc flag? */ |
| 1409 | | device->state().set_state_int(TX0_IOS,1); |
| 1375 | m_maincpu->io_complete(); |
| 1410 | 1376 | break; |
| 1411 | 1377 | |
| 1412 | 1378 | case MTS_SELECTING: |
| 1413 | 1379 | case MTS_SELECTED: |
| 1414 | | switch (state->m_magtape.command) |
| 1380 | switch (m_magtape.command) |
| 1415 | 1381 | { |
| 1416 | 1382 | case 0: /* backspace */ |
| 1417 | 1383 | case 2: /* rewind */ |
| 1418 | 1384 | /* ignore instruction and set rwc flag? */ |
| 1419 | | device->state().set_state_int(TX0_IOS,1); |
| 1385 | m_maincpu->io_complete(); |
| 1420 | 1386 | break; |
| 1421 | 1387 | case 1: /* read */ |
| 1422 | 1388 | case 3: /* write */ |
| 1423 | | state->m_magtape.cpy_pending = TRUE; |
| 1389 | m_magtape.cpy_pending = TRUE; |
| 1424 | 1390 | break; |
| 1425 | 1391 | } |
| 1426 | 1392 | break; |
| r26748 | r26749 | |
| 1433 | 1399 | |
| 1434 | 1400 | IO devices should reset |
| 1435 | 1401 | */ |
| 1436 | | static void tx0_io_reset_callback(device_t *device) |
| 1402 | WRITE_LINE_MEMBER( tx0_state::tx0_io_reset_callback ) |
| 1437 | 1403 | { |
| 1438 | | tx0_state *state = device->machine().driver_data<tx0_state>(); |
| 1439 | | state->m_tape_reader.rcl = state->m_tape_reader.rc = 0; |
| 1440 | | if (state->m_tape_reader.timer) |
| 1441 | | state->m_tape_reader.timer->enable(0); |
| 1404 | m_tape_reader.rcl = m_tape_reader.rc = 0; |
| 1405 | if (m_tape_reader.timer) |
| 1406 | m_tape_reader.timer->enable(0); |
| 1442 | 1407 | |
| 1443 | | if (state->m_tape_puncher.timer) |
| 1444 | | state->m_tape_puncher.timer->enable(0); |
| 1408 | if (m_tape_puncher.timer) |
| 1409 | m_tape_puncher.timer->enable(0); |
| 1445 | 1410 | |
| 1446 | | if (state->m_typewriter.prt_timer) |
| 1447 | | state->m_typewriter.prt_timer->enable(0); |
| 1411 | if (m_typewriter.prt_timer) |
| 1412 | m_typewriter.prt_timer->enable(0); |
| 1448 | 1413 | |
| 1449 | | if (state->m_dis_timer) |
| 1450 | | state->m_dis_timer->enable(0); |
| 1414 | if (m_dis_timer) |
| 1415 | m_dis_timer->enable(0); |
| 1451 | 1416 | } |
| 1452 | 1417 | |
| 1453 | 1418 | |
| r26748 | r26749 | |
| 1537 | 1502 | } |
| 1538 | 1503 | if (control_transitions & tx0_read_in) |
| 1539 | 1504 | { /* set cpu to read instructions from perforated tape */ |
| 1540 | | m_maincpu->set_state_int(TX0_RESET, (UINT64)0); |
| 1505 | m_maincpu->pulse_reset(); |
| 1541 | 1506 | m_maincpu->set_state_int(TX0_RUN, (UINT64)0); |
| 1542 | 1507 | m_maincpu->set_state_int(TX0_RIM, 1); |
| 1543 | 1508 | } |
| r26748 | r26749 | |
| 1600 | 1565 | /* basic machine hardware */ |
| 1601 | 1566 | /* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is approximately 6usec) */ |
| 1602 | 1567 | MCFG_CPU_ADD("maincpu", TX0_64KW, 166667) |
| 1603 | | MCFG_CPU_CONFIG(tx0_reset_param) |
| 1568 | MCFG_TX0_CONFIG( |
| 1569 | WRITELINE( tx0_state, tx0_io_cpy ), |
| 1570 | WRITELINE( tx0_state, tx0_io_r1l ), |
| 1571 | WRITELINE( tx0_state, tx0_io_dis ), |
| 1572 | WRITELINE( tx0_state, tx0_io_r3l ), |
| 1573 | WRITELINE( tx0_state, tx0_io_prt ), |
| 1574 | NULL, |
| 1575 | WRITELINE( tx0_state, tx0_io_p6h ), |
| 1576 | WRITELINE( tx0_state, tx0_io_p7h ), |
| 1577 | WRITELINE( tx0_state, tx0_sel ), |
| 1578 | WRITELINE( tx0_state, tx0_io_reset_callback ) |
| 1579 | ) |
| 1604 | 1580 | MCFG_CPU_PROGRAM_MAP(tx0_64kw_map) |
| 1605 | 1581 | /* dummy interrupt: handles input */ |
| 1606 | 1582 | MCFG_CPU_VBLANK_INT_DRIVER("screen", tx0_state, tx0_interrupt) |
| r26748 | r26749 | |
| 1632 | 1608 | /* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is |
| 1633 | 1609 | approximately 6usec) */ |
| 1634 | 1610 | MCFG_CPU_MODIFY("maincpu") |
| 1635 | | MCFG_CPU_CONFIG(tx0_reset_param) |
| 1636 | 1611 | MCFG_CPU_PROGRAM_MAP(tx0_8kw_map) |
| 1637 | 1612 | /*MCFG_CPU_PORTS(readport, writeport)*/ |
| 1638 | 1613 | MACHINE_CONFIG_END |