trunk/src/emu/cpu/tms9900/tms9980a.c
r25467 | r25468 | |
147 | 147 | void tms9980a_device::mem_read() |
148 | 148 | { |
149 | 149 | UINT8 value; |
150 | | if (m_lowbyte) |
| 150 | switch (m_mem_phase) |
151 | 151 | { |
| 152 | case 1: |
| 153 | m_pass = 4; // make the CPU visit this method more than once |
| 154 | m_dbin_line(ASSERT_LINE); |
| 155 | m_prgspace->set_address(m_address & m_prgaddr_mask & ~1); |
| 156 | if (VERBOSE>7) LOG("tms9980a: set address bus %04x\n", m_address & m_prgaddr_mask & ~1); |
| 157 | m_check_ready = true; |
| 158 | break; |
| 159 | case 2: |
| 160 | // Sample the value on the data bus (high byte) |
| 161 | value = m_prgspace->read_byte(m_address & m_prgaddr_mask & ~1); |
| 162 | if (VERBOSE>7) LOG("tms9980a: memory read high byte %04x -> %02x\n", m_address & m_prgaddr_mask & ~1, value); |
| 163 | m_current_value = (value << 8) & 0xff00; |
| 164 | break; |
| 165 | case 3: |
| 166 | m_prgspace->set_address((m_address & m_prgaddr_mask) | 1); |
| 167 | if (VERBOSE>7) LOG("tms9980a: set address bus %04x\n", (m_address & m_prgaddr_mask) | 1); |
| 168 | break; |
| 169 | case 4: |
| 170 | // Sample the value on the data bus (low byte) |
152 | 171 | value = m_prgspace->read_byte((m_address & m_prgaddr_mask) | 1); |
153 | 172 | m_current_value = m_current_value | (value & 0x00ff); |
154 | | if (VERBOSE>7) LOG("tms9980a: memory read low byte %04x -> complete word %04x\n", (m_address & m_prgaddr_mask) | 1, m_current_value); |
155 | | m_lowbyte = false; |
| 173 | if (VERBOSE>7) LOG("tms9980a: memory read low byte %04x -> %02x -> complete word %04x\n", (m_address & m_prgaddr_mask) | 1, value, m_current_value); |
| 174 | break; |
156 | 175 | } |
157 | | else |
158 | | { |
159 | | value = m_prgspace->read_byte(m_address & 0x3ffe); |
160 | | if (VERBOSE>7) LOG("tms9980a: memory read high byte %04x -> %02x\n", m_address & m_prgaddr_mask, value); |
161 | | m_current_value = (value << 8) & 0xff00; |
162 | | m_lowbyte = true; |
163 | | m_pass = 2; // make the CPU visit this method once more |
164 | | } |
165 | | pulse_clock(2); |
166 | | m_check_ready = true; |
| 176 | pulse_clock(1); |
| 177 | m_mem_phase = (m_mem_phase % 4) +1; |
167 | 178 | } |
168 | 179 | |
| 180 | |
169 | 181 | void tms9980a_device::mem_write() |
170 | 182 | { |
171 | | if (m_lowbyte) |
| 183 | switch (m_mem_phase) |
172 | 184 | { |
173 | | m_prgspace->write_byte((m_address & 0x3ffe) | 1, m_current_value & 0xff); |
174 | | if (VERBOSE>7) LOG("tms9980a: memory write low byte %04x <- %02x\n", (m_address & m_prgaddr_mask) | 1, m_current_value & 0xff); |
175 | | m_lowbyte = false; |
| 185 | case 1: |
| 186 | m_pass = 4; // make the CPU visit this method once more |
| 187 | m_dbin_line(CLEAR_LINE); |
| 188 | m_prgspace->set_address(m_address & m_prgaddr_mask & ~1); |
| 189 | if (VERBOSE>7) LOG("tms9980a: set address bus %04x\n", m_address & m_prgaddr_mask & ~1); |
| 190 | m_prgspace->write_byte(m_address & 0x3ffe & ~1, (m_current_value >> 8)&0xff); |
| 191 | if (VERBOSE>7) LOG("tms9980a: memory write high byte %04x <- %02x\n", m_address & m_prgaddr_mask & ~1, (m_current_value >> 8)&0xff); |
| 192 | m_check_ready = true; |
| 193 | break; |
| 194 | case 2: |
| 195 | // no action here, just wait for READY |
| 196 | break; |
| 197 | case 3: |
| 198 | m_prgspace->set_address((m_address & m_prgaddr_mask) | 1); |
| 199 | if (VERBOSE>7) LOG("tms9980a: set address bus %04x\n", (m_address & m_prgaddr_mask) | 1); |
| 200 | m_prgspace->write_byte((m_address & m_prgaddr_mask) | 1, m_current_value & 0xff); |
| 201 | if (VERBOSE>7) LOG("tms9980a: memory write low byte %04x <- %02x\n", (m_address & m_prgaddr_mask) | 1, m_current_value & 0xff); |
| 202 | break; |
| 203 | case 4: |
| 204 | // no action here, just wait for READY |
| 205 | break; |
176 | 206 | } |
177 | | else |
178 | | { |
179 | | m_prgspace->write_byte(m_address & 0x3ffe, (m_current_value >> 8)&0xff); |
180 | | if (VERBOSE>7) LOG("tms9980a: memory write high byte %04x <- %02x\n", m_address & m_prgaddr_mask, (m_current_value >> 8)&0xff); |
181 | | m_lowbyte = true; |
182 | | m_pass = 2; // make the CPU visit this method once more |
183 | | } |
184 | | pulse_clock(2); |
185 | | m_check_ready = true; |
| 207 | pulse_clock(1); |
| 208 | m_mem_phase = (m_mem_phase % 4) +1; |
186 | 209 | } |
187 | 210 | |
188 | 211 | void tms9980a_device::acquire_instruction() |
189 | 212 | { |
190 | | if (!m_lowbyte) |
| 213 | if (m_mem_phase == 1) |
191 | 214 | { |
192 | 215 | m_iaq_line(ASSERT_LINE); |
193 | 216 | m_address = PC; |
194 | 217 | m_first_cycle = m_icount; |
195 | | mem_read(); |
196 | 218 | } |
197 | | else |
| 219 | mem_read(); |
| 220 | |
| 221 | if (m_mem_phase == 1) // changed by mem_read and wrapped |
198 | 222 | { |
199 | | mem_read(); |
200 | 223 | decode(m_current_value); |
201 | 224 | if (VERBOSE>3) LOG("tms9980a: ===== Next operation %04x (%s) at %04x =====\n", IR, opname[m_command], PC); |
202 | 225 | debugger_instruction_hook(this, PC); |
r25467 | r25468 | |
205 | 228 | // IAQ will be cleared in the main loop |
206 | 229 | } |
207 | 230 | |
| 231 | |
| 232 | |
208 | 233 | /**************************************************************************/ |
209 | 234 | UINT32 tms9980a_device::execute_min_cycles() const |
210 | 235 | { |
trunk/src/emu/cpu/tms9900/tms9995.c
r25467 | r25468 | |
158 | 158 | m_external_operation.resolve(conf->external_callback, *this); |
159 | 159 | m_iaq_line.resolve(conf->iaq_line, *this); |
160 | 160 | m_clock_out_line.resolve(conf->clock_out, *this); |
161 | | m_wait_line.resolve(conf->wait_line, *this); |
162 | 161 | m_holda_line.resolve(conf->holda_line, *this); |
| 162 | m_dbin_line.resolve(conf->dbin_line, *this); |
163 | 163 | |
164 | 164 | m_mp9537 = (conf->mode==NO_INTERNAL_RAM); |
165 | 165 | m_check_overflow = (conf->overflow==OVERFLOW_INT); |
r25467 | r25468 | |
1086 | 1086 | do |
1087 | 1087 | { |
1088 | 1088 | // Normal operation |
1089 | | if (m_check_ready && m_ready_state == false) |
| 1089 | if (m_check_ready && m_ready == false) |
1090 | 1090 | { |
1091 | 1091 | // We are in a wait state |
1092 | | set_wait_state(true); |
1093 | 1092 | if (VERBOSE>2) LOG("tms9995: wait state\n"); |
1094 | 1093 | // The clock output should be used to change the state of an outer |
1095 | 1094 | // device which operates the READY line |
r25467 | r25468 | |
1105 | 1104 | } |
1106 | 1105 | else |
1107 | 1106 | { |
1108 | | set_wait_state(false); |
1109 | 1107 | set_hold_state(false); |
1110 | 1108 | |
1111 | 1109 | m_check_ready = false; |
r25467 | r25468 | |
1189 | 1187 | for (int i=0; i < count; i++) |
1190 | 1188 | { |
1191 | 1189 | m_clock_out_line(ASSERT_LINE); |
| 1190 | m_ready = m_ready_bufd && !m_request_auto_wait_state; // get the latched READY state |
1192 | 1191 | m_clock_out_line(CLEAR_LINE); |
1193 | 1192 | m_icount--; // This is the only location where we count down the cycles. |
1194 | | if (VERBOSE>7) LOG("tms9995: pulse_clock\n"); |
| 1193 | if (VERBOSE>7) |
| 1194 | { |
| 1195 | if (m_check_ready) LOG("tms9995: pulse_clock, READY=%d, auto_wait=%d\n", m_ready_bufd? 1:0, m_auto_wait? 1:0); |
| 1196 | else LOG("tms9995: pulse_clock\n"); |
| 1197 | } |
| 1198 | m_request_auto_wait_state = false; |
1195 | 1199 | if (m_flag[0] == false && m_flag[1] == true) trigger_decrementer(); |
1196 | 1200 | } |
1197 | 1201 | } |
r25467 | r25468 | |
1210 | 1214 | } |
1211 | 1215 | |
1212 | 1216 | /* |
1213 | | Signal READY to the CPU. When cleared, the CPU enters wait states. |
| 1217 | Signal READY to the CPU. When cleared, the CPU enters wait states. This |
| 1218 | becomes effective on a clock pulse. |
1214 | 1219 | */ |
1215 | 1220 | void tms9995_device::set_ready(int state) |
1216 | 1221 | { |
1217 | | if (VERBOSE>5) LOG("tms9995: set READY = %d\n", state); |
1218 | | m_ready_state = (state==ASSERT_LINE); |
| 1222 | m_ready_bufd = (state==ASSERT_LINE); |
| 1223 | if (VERBOSE>7) LOG("tms9995: set READY = %d\n", m_ready_bufd? 1 : 0); |
1219 | 1224 | } |
1220 | 1225 | |
1221 | 1226 | /* |
r25467 | r25468 | |
1227 | 1232 | // And don't forget that prefetch is a 2-pass operation, so this method |
1228 | 1233 | // will be called a second time. Only when the lowbyte has been fetched, |
1229 | 1234 | // continue with the next step |
1230 | | if (!m_lowbyte) command_completed(); |
| 1235 | if (m_mem_phase==1) command_completed(); |
1231 | 1236 | } |
1232 | 1237 | |
1233 | 1238 | /* |
1234 | | Enter or leave the wait state. We only operate the WAIT line when there is a change. |
1235 | | */ |
1236 | | inline void tms9995_device::set_wait_state(bool state) |
1237 | | { |
1238 | | if (m_wait_state != state) m_wait_line(state? ASSERT_LINE : CLEAR_LINE); |
1239 | | m_wait_state = state; |
1240 | | } |
1241 | | |
1242 | | /* |
1243 | 1239 | Enter or leave the hold state. We only operate the HOLDA line when there is a change. |
1244 | 1240 | */ |
1245 | 1241 | inline void tms9995_device::set_hold_state(bool state) |
r25467 | r25468 | |
1307 | 1303 | bool check_int = (m_instruction->command != XOP && m_instruction->command != BLWP); |
1308 | 1304 | int intmask = ST & 0x000f; |
1309 | 1305 | |
1310 | | if (m_lowbyte) |
| 1306 | if (m_mem_phase == 1) |
1311 | 1307 | { |
1312 | | prefetch_and_decode(); |
1313 | | return; |
1314 | | } |
1315 | | |
1316 | | // Check interrupt lines |
1317 | | if (m_nmi_active) |
1318 | | { |
1319 | | if (VERBOSE>7) LOG("tms9995: Checking interrupts ... NMI active\n"); |
1320 | | m_int_pending |= PENDING_NMI; |
1321 | | m_idle_state = false; |
1322 | | PC = (PC + 2) & 0xfffe; // we have not prefetched the next instruction |
1323 | | } |
1324 | | else |
1325 | | { |
1326 | | m_int_pending = 0; |
1327 | | |
1328 | | if (m_int1_active && intmask >= 1 && check_int) m_int_pending |= PENDING_LEVEL1; |
1329 | | if (m_int_overflow && intmask >= 2 && check_int) m_int_pending |= PENDING_OVERFLOW; |
1330 | | if (m_int_decrementer && intmask >= 3 && check_int) m_int_pending |= PENDING_DECR; |
1331 | | if (m_int4_active && intmask >= 4 && check_int) m_int_pending |= PENDING_LEVEL4; |
1332 | | |
1333 | | if (m_int_pending!=0) |
| 1308 | // Check interrupt lines |
| 1309 | if (m_nmi_active) |
1334 | 1310 | { |
1335 | | if (m_idle_state) |
1336 | | { |
1337 | | m_idle_state = false; |
1338 | | if (VERBOSE>7) LOG("tms9995: Interrupt occured, terminate IDLE state\n"); |
1339 | | } |
1340 | | PC = PC + 2; // PC must be advanced (see flow chart), but no prefetch |
1341 | | if (VERBOSE>7) LOG("tms9995: Interrupts pending; no prefetch; advance PC to %04x\n", PC); |
| 1311 | if (VERBOSE>7) LOG("tms9995: Checking interrupts ... NMI active\n"); |
| 1312 | m_int_pending |= PENDING_NMI; |
| 1313 | m_idle_state = false; |
| 1314 | PC = (PC + 2) & 0xfffe; // we have not prefetched the next instruction |
| 1315 | return; |
1342 | 1316 | } |
1343 | 1317 | else |
1344 | 1318 | { |
1345 | | if (VERBOSE>7) LOG("tms9995: Checking interrupts ... none pending\n"); |
1346 | | // No pending interrupts |
1347 | | if (check_idle && m_idle_state) |
| 1319 | m_int_pending = 0; |
| 1320 | |
| 1321 | if (m_int1_active && intmask >= 1 && check_int) m_int_pending |= PENDING_LEVEL1; |
| 1322 | if (m_int_overflow && intmask >= 2 && check_int) m_int_pending |= PENDING_OVERFLOW; |
| 1323 | if (m_int_decrementer && intmask >= 3 && check_int) m_int_pending |= PENDING_DECR; |
| 1324 | if (m_int4_active && intmask >= 4 && check_int) m_int_pending |= PENDING_LEVEL4; |
| 1325 | |
| 1326 | if (m_int_pending!=0) |
1348 | 1327 | { |
1349 | | if (VERBOSE>7) LOG("tms9995: IDLE state\n"); |
1350 | | // We are IDLE, stay in the loop and do not advance the PC |
1351 | | m_pass = 2; |
1352 | | pulse_clock(1); |
| 1328 | if (m_idle_state) |
| 1329 | { |
| 1330 | m_idle_state = false; |
| 1331 | if (VERBOSE>7) LOG("tms9995: Interrupt occured, terminate IDLE state\n"); |
| 1332 | } |
| 1333 | PC = PC + 2; // PC must be advanced (see flow chart), but no prefetch |
| 1334 | if (VERBOSE>7) LOG("tms9995: Interrupts pending; no prefetch; advance PC to %04x\n", PC); |
| 1335 | return; |
1353 | 1336 | } |
1354 | 1337 | else |
1355 | 1338 | { |
1356 | | prefetch_and_decode(); |
| 1339 | if (VERBOSE>7) LOG("tms9995: Checking interrupts ... none pending\n"); |
| 1340 | // No pending interrupts |
| 1341 | if (check_idle && m_idle_state) |
| 1342 | { |
| 1343 | if (VERBOSE>7) LOG("tms9995: IDLE state\n"); |
| 1344 | // We are IDLE, stay in the loop and do not advance the PC |
| 1345 | m_pass = 2; |
| 1346 | pulse_clock(1); |
| 1347 | return; |
| 1348 | } |
1357 | 1349 | } |
1358 | 1350 | } |
1359 | 1351 | } |
| 1352 | |
| 1353 | // We reach this point in phase 1 if there is no interrupt and in all other phases |
| 1354 | prefetch_and_decode(); |
1360 | 1355 | } |
1361 | 1356 | |
1362 | 1357 | /* |
r25467 | r25468 | |
1367 | 1362 | */ |
1368 | 1363 | void tms9995_device::prefetch_and_decode() |
1369 | 1364 | { |
1370 | | if (m_lowbyte) |
| 1365 | if (m_mem_phase==1) |
1371 | 1366 | { |
1372 | | // Second pass for getting the instruction |
1373 | | if (VERBOSE>6) LOG("tms9995: Prefetch memory access (second pass)\n"); |
1374 | | word_read(); |
1375 | | decode(m_current_value); // This is for free; in reality it is in parallel with the next memory operation |
1376 | | m_address = m_address_copy; // restore m_address |
1377 | | m_current_value = m_value_copy; // restore m_current_value |
1378 | | PC = (PC + 2) & 0xfffe; // advance PC |
1379 | | m_iaq_line(CLEAR_LINE); |
1380 | | if (VERBOSE>5) LOG("tms9995: ++++ Prefetch done ++++\n"); |
1381 | | m_lowbyte = false; |
1382 | | } |
1383 | | else |
1384 | | { |
1385 | 1367 | // Fetch next instruction |
1386 | 1368 | // Save these values; they have been computed during the current instruction execution |
1387 | 1369 | m_address_copy = m_address; |
1388 | 1370 | m_value_copy = m_current_value; |
1389 | | |
1390 | 1371 | m_iaq_line(ASSERT_LINE); |
1391 | | |
1392 | 1372 | m_address = PC; |
1393 | | |
1394 | 1373 | if (VERBOSE>5) LOG("tms9995: **** Prefetching new instruction at %04x ****\n", PC); |
| 1374 | } |
1395 | 1375 | |
1396 | | m_lowbyte = false; // for mem_read |
1397 | | word_read(); // this is where the clock pulses occur |
| 1376 | word_read(); |
1398 | 1377 | |
1399 | | if (!m_lowbyte) |
1400 | | { |
1401 | | // Only if we got the word in one pass |
1402 | | decode(m_current_value); // This is for free; in reality it is in parallel with the next memory operation |
1403 | | |
1404 | | m_address = m_address_copy; // restore m_address |
1405 | | m_current_value = m_value_copy; // restore m_current_value |
1406 | | PC = (PC + 2) & 0xfffe; // advance PC |
1407 | | |
1408 | | m_iaq_line(CLEAR_LINE); |
1409 | | } |
| 1378 | if (m_mem_phase==1) |
| 1379 | { |
| 1380 | // We're back in phase 1, i.e. the whole prefetch is done |
| 1381 | decode(m_current_value); // This is for free; in reality it is in parallel with the next memory operation |
| 1382 | m_address = m_address_copy; // restore m_address |
| 1383 | m_current_value = m_value_copy; // restore m_current_value |
| 1384 | PC = (PC + 2) & 0xfffe; // advance PC |
| 1385 | m_iaq_line(CLEAR_LINE); |
| 1386 | if (VERBOSE>5) LOG("tms9995: ++++ Prefetch done ++++\n"); |
1410 | 1387 | } |
1411 | 1388 | } |
1412 | 1389 | |
r25467 | r25468 | |
1447 | 1424 | // Pseudo state at the end of the current instruction cycle sequence |
1448 | 1425 | if (VERBOSE>4) |
1449 | 1426 | { |
1450 | | LOG("tms9995: +++++ Instruction %04x (%s) completed +++++\n", m_instruction->IR, opname[m_instruction->command]); |
| 1427 | LOG("tms9995: +++++ Instruction %04x (%s) completed", m_instruction->IR, opname[m_instruction->command]); |
1451 | 1428 | int cycles = m_first_cycle - m_icount; |
1452 | 1429 | // Avoid nonsense values due to expired and resumed main loop |
1453 | | if (cycles > 0 && cycles < 10000) LOG("tms9995: Consumed %d cycles\n", cycles); |
| 1430 | if (cycles > 0 && cycles < 10000) LOG(", consumed %d cycles", cycles); |
| 1431 | LOG(" +++++\n"); |
1454 | 1432 | } |
1455 | 1433 | |
1456 | 1434 | if (m_int_pending != 0) |
r25467 | r25468 | |
1484 | 1462 | |
1485 | 1463 | m_nmi_state = false; |
1486 | 1464 | m_hold_state = false; |
1487 | | m_wait_state = false; |
1488 | | m_lowbyte = false; |
| 1465 | m_mem_phase = 1; |
1489 | 1466 | m_check_hold = false; |
1490 | 1467 | m_word_access = false; |
1491 | 1468 | m_int4_active = false; |
r25467 | r25468 | |
1500 | 1477 | |
1501 | 1478 | // The auto-wait state generation is turned on when the READY line is cleared |
1502 | 1479 | // on RESET. |
1503 | | m_auto_wait_state = !m_ready_state; |
1504 | | if (VERBOSE>0) LOG("tms9995: RESET; automatic wait state creation is %s\n", m_auto_wait_state? "enabled":"disabled"); |
1505 | | m_ready_state = true; |
| 1480 | m_auto_wait = !m_ready_bufd; |
| 1481 | if (VERBOSE>0) LOG("tms9995: RESET; automatic wait state creation is %s\n", m_auto_wait? "enabled":"disabled"); |
| 1482 | // We reset the READY flag, or the CPU will not start |
| 1483 | m_ready_bufd = true; |
1506 | 1484 | } |
1507 | 1485 | else |
1508 | 1486 | { |
r25467 | r25468 | |
1574 | 1552 | m_instruction->byteop = false; |
1575 | 1553 | m_instruction->command = INTR; |
1576 | 1554 | m_pass = m_reset? 1 : 2; |
| 1555 | m_from_reset = m_reset; |
1577 | 1556 | |
1578 | 1557 | if (m_reset) |
1579 | 1558 | { |
r25467 | r25468 | |
1604 | 1583 | void tms9995_device::mem_read() |
1605 | 1584 | { |
1606 | 1585 | // First determine whether the memory is inside the CPU |
1607 | | // On-chip memory is F000 ... F0F9, F0FC-FFF9 = off-chip, FFFA/B = Decrementer |
| 1586 | // On-chip memory is F000 ... F0F9, F0FA-FFF9 = off-chip, FFFA/B = Decrementer |
1608 | 1587 | // FFFC-FFFF = NMI vector (on-chip) |
1609 | 1588 | // There is a variant of the TMS9995 with no on-chip RAM which was used |
1610 | 1589 | // for the TI-99/8 (9537). |
r25467 | r25468 | |
1641 | 1620 | } |
1642 | 1621 | else |
1643 | 1622 | { |
1644 | | // This is a off-chip access |
| 1623 | // This is an off-chip access |
1645 | 1624 | m_check_ready = true; |
1646 | | if (m_lowbyte) |
| 1625 | UINT8 value; |
| 1626 | UINT16 address = m_address; |
| 1627 | |
| 1628 | switch (m_mem_phase) |
1647 | 1629 | { |
1648 | | // This is always the odd address |
1649 | | // With the OR we can ensure that we do not skip to an even address |
1650 | | // when we try to read a word from an odd address |
1651 | | m_current_value |= m_prgspace->read_byte(m_address | 0x0001); |
1652 | | m_lowbyte = false; |
1653 | | if (VERBOSE>3) LOG("tms9995: read external memory, second pass (address %04x, complete word = %04x)\n", m_address | 1, m_current_value); |
1654 | | m_check_hold = true; |
1655 | | } |
1656 | | else |
1657 | | { |
1658 | | UINT16 address = m_address; |
| 1630 | case 1: |
| 1631 | // Set address |
| 1632 | // If this is a word access, 4 passes, else 2 passes |
| 1633 | m_dbin_line(ASSERT_LINE); |
1659 | 1634 | if (m_word_access || !m_instruction->byteop) |
1660 | 1635 | { |
1661 | | // We have to come here a second time; do not advance the MPC |
1662 | | // if the address value is even |
1663 | | m_lowbyte = true; |
1664 | | m_pass = 2; |
| 1636 | m_pass = 4; |
| 1637 | // For word accesses, we always start at the even address |
1665 | 1638 | address &= 0xfffe; |
1666 | | m_check_hold = false; |
1667 | 1639 | } |
1668 | | m_current_value = m_prgspace->read_byte(address) << 8; |
1669 | | if (VERBOSE>3) |
1670 | | { |
1671 | | if (m_pass==2) LOG("tms9995: read external memory, first pass (address %04x, value %02x)\n", address, (m_current_value>>8)&0xff); |
1672 | | else LOG("tms9995: read external memory (single pass), address %04x, value=%04x)\n", address, m_current_value); |
1673 | | } |
| 1640 | else m_pass = 2; |
| 1641 | |
| 1642 | m_check_hold = false; |
| 1643 | if (VERBOSE>7) LOG("tms9995: set address bus %04x\n", m_address & ~1); |
| 1644 | m_prgspace->set_address(address); |
| 1645 | m_request_auto_wait_state = m_auto_wait; |
| 1646 | break; |
| 1647 | case 2: |
| 1648 | // Sample the value on the data bus (high byte) |
| 1649 | if (m_word_access || !m_instruction->byteop) address &= 0xfffe; |
| 1650 | value = m_prgspace->read_byte(address); |
| 1651 | if (VERBOSE>7) LOG("tms9995: memory read byte %04x -> %02x\n", m_address & ~1, value); |
| 1652 | m_current_value = (value << 8) & 0xff00; |
| 1653 | break; |
| 1654 | case 3: |
| 1655 | // Set address + 1 (unless byte command) |
| 1656 | if (VERBOSE>7) LOG("tms9995: set address bus %04x\n", m_address | 1); |
| 1657 | m_prgspace->set_address(m_address | 1); |
| 1658 | break; |
| 1659 | case 4: |
| 1660 | // Read low byte |
| 1661 | value = m_prgspace->read_byte(m_address | 1); |
| 1662 | m_current_value |= value; |
| 1663 | if (VERBOSE>3) LOG("tms9995: memory read byte %04x -> %02x, complete word = %04x\n", m_address | 1, value, m_current_value); |
| 1664 | m_check_hold = true; |
| 1665 | break; |
1674 | 1666 | } |
1675 | | if (m_auto_wait_state) |
1676 | | { |
1677 | | if (VERBOSE>7) LOG("tms9995: Next pulse is auto wait\n"); |
1678 | | pulse_clock(1); |
1679 | | } |
| 1667 | |
| 1668 | m_mem_phase = (m_mem_phase % 4) +1; |
| 1669 | |
| 1670 | // Reset to 1 when we are done |
| 1671 | if (m_pass==1) m_mem_phase = 1; |
1680 | 1672 | } |
1681 | 1673 | pulse_clock(1); |
1682 | 1674 | } |
r25467 | r25468 | |
1738 | 1730 | pulse_clock(1); |
1739 | 1731 | return; |
1740 | 1732 | } |
1741 | | |
1742 | 1733 | bool onchip = (((m_address & 0xff00)==0xf000 && (m_address < 0xf0fc)) || ((m_address & 0xfffc)==0xfffc)) && !m_mp9537; |
1743 | 1734 | |
1744 | 1735 | if (onchip) |
r25467 | r25468 | |
1753 | 1744 | } |
1754 | 1745 | else |
1755 | 1746 | { |
| 1747 | // This is an off-chip access |
1756 | 1748 | m_check_ready = true; |
| 1749 | UINT16 address = m_address; |
| 1750 | switch (m_mem_phase) |
| 1751 | { |
| 1752 | case 1: |
| 1753 | // Set address |
| 1754 | // If this is a word access, 4 passes, else 2 passes |
| 1755 | m_dbin_line(CLEAR_LINE); |
1757 | 1756 | |
1758 | | if (m_lowbyte) |
1759 | | { |
1760 | | // see above in mem_read |
1761 | | m_prgspace->write_byte(m_address | 0x0001, m_current_value & 0xff); |
1762 | | m_lowbyte = false; |
1763 | | if (VERBOSE>3) LOG("tms9995: write second pass (address %04x, value %02x)\n", m_address | 0x0001, m_current_value & 0xff); |
1764 | | m_check_hold = true; |
1765 | | } |
1766 | | else |
1767 | | { |
1768 | | UINT16 address = m_address; |
1769 | 1757 | if (m_word_access || !m_instruction->byteop) |
1770 | 1758 | { |
1771 | | // We have to come here a second time; do not advance the MPC |
1772 | | // if the address value is even |
1773 | | m_lowbyte = true; |
1774 | | m_pass = 2; |
| 1759 | m_pass = 4; |
1775 | 1760 | address &= 0xfffe; |
1776 | | m_check_hold = false; |
1777 | 1761 | } |
1778 | | if (VERBOSE>3) |
1779 | | { |
1780 | | if (m_pass==2) LOG("tms9995: write external memory, first pass (address %04x, value %02x)\n", address, (m_current_value>>8)&0xff); |
1781 | | else LOG("tms9995: write external memory (single pass), address %04x, value=%02x\n", address, (m_current_value>>8)&0xff); |
1782 | | } |
1783 | | m_prgspace->write_byte(address, (m_current_value >> 8)& 0xff); |
| 1762 | else m_pass = 2; |
| 1763 | |
| 1764 | m_check_hold = false; |
| 1765 | if (VERBOSE>7) LOG("tms9995: set address bus %04x\n", address); |
| 1766 | m_prgspace->set_address(address); |
| 1767 | if (VERBOSE>7) LOG("tms9995: memory write byte %04x <- %02x\n", address, (m_current_value >> 8)&0xff); |
| 1768 | m_prgspace->write_byte(address, (m_current_value >> 8)&0xff); |
| 1769 | break; |
| 1770 | |
| 1771 | case 2: |
| 1772 | // no action here, just wait for READY |
| 1773 | break; |
| 1774 | case 3: |
| 1775 | // Set address + 1 (unless byte command) |
| 1776 | if (VERBOSE>7) LOG("tms9995: set address bus %04x\n", m_address | 1); |
| 1777 | m_prgspace->set_address(m_address | 1); |
| 1778 | if (VERBOSE>7) LOG("tms9995: memory write byte %04x <- %02x\n", m_address | 1, m_current_value & 0xff); |
| 1779 | m_prgspace->write_byte(m_address | 1, m_current_value & 0xff); |
| 1780 | break; |
| 1781 | case 4: |
| 1782 | // no action here, just wait for READY |
| 1783 | m_check_hold = true; |
| 1784 | break; |
1784 | 1785 | } |
1785 | 1786 | |
1786 | | if (m_auto_wait_state) |
1787 | | { |
1788 | | if (VERBOSE>7) LOG("tms9995: Next pulse is auto wait\n"); |
1789 | | pulse_clock(1); |
1790 | | } |
| 1787 | m_mem_phase = (m_mem_phase % 4) +1; |
| 1788 | |
| 1789 | // Reset to 1 when we are done |
| 1790 | if (m_pass==1) m_mem_phase = 1; |
1791 | 1791 | } |
1792 | 1792 | pulse_clock(1); |
1793 | 1793 | } |
r25467 | r25468 | |
2072 | 2072 | } |
2073 | 2073 | |
2074 | 2074 | m_get_destination = true; |
2075 | | m_lowbyte = false; |
| 2075 | m_mem_phase = 1; |
2076 | 2076 | m_address_add = 0; |
2077 | 2077 | MPC--; // will be increased in the mail loop |
2078 | 2078 | if (VERBOSE>8) LOG("tms9995: *** Operand address derivation; address=%04x; index=%d\n", m_address, MPC+1); |
r25467 | r25468 | |
2087 | 2087 | m_address_saved = m_current_value; // need a special return so we do not lose the value |
2088 | 2088 | m_current_value += m_instruction->byteop? 1 : 2; |
2089 | 2089 | m_address = (WP + (m_regnumber<<1)) & 0xffff; |
2090 | | m_lowbyte = false; |
| 2090 | m_mem_phase = 1; |
2091 | 2091 | pulse_clock(1); |
2092 | 2092 | } |
2093 | 2093 | |
r25467 | r25468 | |
2101 | 2101 | m_address_add = m_current_value; |
2102 | 2102 | m_address = PC; |
2103 | 2103 | PC = (PC + 2) & 0xfffe; |
2104 | | m_lowbyte = false; |
| 2104 | m_mem_phase = 1; |
2105 | 2105 | pulse_clock(1); |
2106 | 2106 | } |
2107 | 2107 | |
r25467 | r25468 | |
2112 | 2112 | m_address = PC; |
2113 | 2113 | m_source_value = m_current_value; // needed for AI, ANDI, ORI |
2114 | 2114 | PC = (PC + 2) & 0xfffe; |
2115 | | m_lowbyte = false; |
| 2115 | m_mem_phase = 1; |
2116 | 2116 | } |
2117 | 2117 | |
2118 | 2118 | /************************************************************************** |
r25467 | r25468 | |
3227 | 3227 | |
3228 | 3228 | if (((m_int_pending & PENDING_MID)!=0) && m_nmi_active) |
3229 | 3229 | { |
3230 | | if (VERBOSE>5) LOG("tms9995: interrupt service (5): NMI active after context switch\n"); |
| 3230 | if (VERBOSE>5) LOG("tms9995: interrupt service (6): NMI active after context switch\n"); |
3231 | 3231 | m_int_pending &= ~PENDING_MID; |
3232 | 3232 | m_address = 0xfffc; |
3233 | 3233 | m_intmask = 0; |
r25467 | r25468 | |
3235 | 3235 | } |
3236 | 3236 | else |
3237 | 3237 | { |
3238 | | if (m_reset) |
| 3238 | if (m_from_reset) |
3239 | 3239 | { |
3240 | | if (VERBOSE>5) LOG("tms9995: interrupt service (5): RESET completed\n"); |
| 3240 | if (VERBOSE>5) LOG("tms9995: interrupt service (6): RESET completed\n"); |
3241 | 3241 | // We came from the RESET interrupt |
3242 | | m_reset = false; |
| 3242 | m_from_reset = false; |
3243 | 3243 | ST &= 0x01ff; |
3244 | 3244 | m_mid_flag = false; |
3245 | 3245 | // FLAG0 and FLAG1 are also set to zero after RESET ([1], sect. 2.3.1.2.2) |
trunk/src/emu/cpu/tms9900/tms9900.c
r25467 | r25468 | |
177 | 177 | m_clock_out_line.resolve(conf->clock_out, *this); |
178 | 178 | m_wait_line.resolve(conf->wait_line, *this); |
179 | 179 | m_holda_line.resolve(conf->holda_line, *this); |
| 180 | m_dbin_line.resolve(conf->dbin_line, *this); // we need this for the set_address operation |
180 | 181 | |
181 | 182 | // set our instruction counter |
182 | 183 | m_icountptr = &m_icount; |
r25467 | r25468 | |
202 | 203 | void tms99xx_device::device_stop() |
203 | 204 | { |
204 | 205 | int k = 0; |
205 | | if (VERBOSE>8) LOG("tms99xx: Deleting lookup tables\n"); |
| 206 | if (VERBOSE>3) LOG("tms99xx: Deleting lookup tables\n"); |
206 | 207 | while (m_lotables[k]!=NULL) delete[] m_lotables[k++]; |
207 | 208 | } |
208 | 209 | |
r25467 | r25468 | |
1122 | 1123 | m_program[MPC] != MEMORY_READ && m_program[MPC] != MEMORY_WRITE && |
1123 | 1124 | m_program[MPC] != REG_READ && m_program[MPC] != REG_WRITE))) |
1124 | 1125 | { |
1125 | | if (VERBOSE>5) LOG("tms99xx: hold state\n"); |
| 1126 | if (VERBOSE>2) LOG("tms99xx: hold state\n"); |
1126 | 1127 | if (!m_hold_acknowledged) acknowledge_hold(); |
1127 | 1128 | pulse_clock(1); |
1128 | 1129 | } |
1129 | 1130 | else |
1130 | 1131 | { |
1131 | 1132 | // Normal operation |
1132 | | if (m_check_ready && m_ready_state == false) |
| 1133 | if (m_check_ready && m_ready == false) |
1133 | 1134 | { |
1134 | 1135 | // We are in a wait state |
1135 | 1136 | set_wait_state(true); |
1136 | | if (VERBOSE>5) LOG("tms99xx: wait state\n"); |
| 1137 | if (VERBOSE>2) LOG("tms99xx: wait state\n"); |
1137 | 1138 | // The clock output should be used to change the state of an outer |
1138 | 1139 | // device which operates the READY line |
1139 | 1140 | pulse_clock(1); |
r25467 | r25468 | |
1157 | 1158 | { |
1158 | 1159 | m_pass = 1; |
1159 | 1160 | MPC++; |
| 1161 | m_mem_phase = 1; |
1160 | 1162 | m_iaq_line(CLEAR_LINE); |
1161 | 1163 | } |
1162 | 1164 | } |
r25467 | r25468 | |
1214 | 1216 | m_command = INTR; |
1215 | 1217 | m_idle_state = false; |
1216 | 1218 | m_external_operation(IDLE_OP, 0); |
1217 | | m_lowbyte = false; |
1218 | 1219 | |
1219 | 1220 | m_state = 0; |
1220 | 1221 | |
| 1222 | m_dbin_line(ASSERT_LINE); |
| 1223 | |
1221 | 1224 | // If reset, we just start with execution, otherwise we put the MPC |
1222 | 1225 | // on the first microinstruction, which also means that the main loop shall |
1223 | 1226 | // leave it where it is. So we pretend we have another pass to do. |
r25467 | r25468 | |
1227 | 1230 | { |
1228 | 1231 | m_irq_level = RESET_INT; |
1229 | 1232 | |
1230 | | m_ready_state = true; |
| 1233 | m_ready_bufd = true; |
| 1234 | m_ready = true; |
1231 | 1235 | m_load_state = false; |
1232 | 1236 | m_hold_state = false; |
1233 | 1237 | m_hold_acknowledged = false; |
1234 | 1238 | m_wait_state = false; |
1235 | 1239 | IR = 0; |
1236 | 1240 | ST = 0; |
| 1241 | m_mem_phase = 1; |
1237 | 1242 | |
1238 | 1243 | m_reset = false; |
1239 | 1244 | } |
r25467 | r25468 | |
1251 | 1256 | for (int i=0; i < count; i++) |
1252 | 1257 | { |
1253 | 1258 | m_clock_out_line(ASSERT_LINE); |
| 1259 | m_ready = m_ready_bufd; // get the latched READY state |
1254 | 1260 | m_clock_out_line(CLEAR_LINE); |
1255 | 1261 | m_icount--; // This is the only location where we count down the cycles. |
1256 | | if (VERBOSE>7) LOG("tms99xx: pulse_clock\n"); |
| 1262 | if (VERBOSE>7) |
| 1263 | { |
| 1264 | if (m_check_ready) LOG("tms99xx: pulse_clock, READY=%d\n", m_ready? 1:0); |
| 1265 | else LOG("tms99xx: pulse_clock\n"); |
| 1266 | } |
1257 | 1267 | } |
1258 | 1268 | } |
1259 | 1269 | |
r25467 | r25468 | |
1280 | 1290 | } |
1281 | 1291 | |
1282 | 1292 | /* |
1283 | | Signal READY to the CPU. When cleared, the CPU enters wait states. |
| 1293 | Signal READY to the CPU. When cleared, the CPU enters wait states. This |
| 1294 | becomes effective on a clock pulse. |
1284 | 1295 | */ |
1285 | 1296 | void tms99xx_device::set_ready(int state) |
1286 | 1297 | { |
1287 | | m_ready_state = (state==ASSERT_LINE); |
| 1298 | m_ready_bufd = (state==ASSERT_LINE); |
1288 | 1299 | } |
1289 | 1300 | |
1290 | 1301 | void tms99xx_device::abort_operation() |
r25467 | r25468 | |
1344 | 1355 | m_program = decoded->prog; |
1345 | 1356 | MPC = -1; |
1346 | 1357 | m_command = decoded->id; |
1347 | | if (VERBOSE>7) LOG("tms99xx: Command decoded as id %d, %s, base opcode %04x\n", m_command, opname[m_command], decoded->opcode); |
| 1358 | if (VERBOSE>8) LOG("tms99xx: Command decoded as id %d, %s, base opcode %04x\n", m_command, opname[m_command], decoded->opcode); |
1348 | 1359 | // Byte operations are either format 1 with the byte flag set |
1349 | 1360 | // or format 4 (CRU multi bit operations) with 1-8 bits to transfer. |
1350 | 1361 | m_byteop = ((decoded->format==1 && ((IR & 0x1000)!=0)) |
r25467 | r25468 | |
1360 | 1371 | |
1361 | 1372 | void tms99xx_device::acquire_instruction() |
1362 | 1373 | { |
1363 | | m_iaq_line(ASSERT_LINE); |
1364 | | m_address = PC; |
1365 | | m_first_cycle = m_icount; |
| 1374 | if (m_mem_phase == 1) |
| 1375 | { |
| 1376 | m_iaq_line(ASSERT_LINE); |
| 1377 | m_address = PC; |
| 1378 | m_first_cycle = m_icount; |
| 1379 | } |
| 1380 | |
1366 | 1381 | mem_read(); |
1367 | | decode(m_current_value); |
1368 | | if (VERBOSE>3) LOG("tms99xx: ===== Next operation %04x (%s) at %04x =====\n", IR, opname[m_command], PC); |
1369 | | debugger_instruction_hook(this, PC); |
1370 | | PC = (PC + 2) & 0xfffe & m_prgaddr_mask; |
1371 | | // IAQ will be cleared in the main loop |
| 1382 | |
| 1383 | if (m_mem_phase == 1) |
| 1384 | { |
| 1385 | decode(m_current_value); |
| 1386 | if (VERBOSE>3) LOG("tms99xx: ===== Next operation %04x (%s) at %04x =====\n", IR, opname[m_command], PC); |
| 1387 | debugger_instruction_hook(this, PC); |
| 1388 | PC = (PC + 2) & 0xfffe & m_prgaddr_mask; |
| 1389 | // IAQ will be cleared in the main loop |
| 1390 | } |
1372 | 1391 | } |
1373 | 1392 | |
1374 | 1393 | /* |
1375 | | Memory read: |
1376 | | 1) Pulse clock (done above) |
1377 | | 2) Set address (we also get the value right here) |
1378 | | 3) Pulse clock |
1379 | | 4) If READY=L (WAIT=H, GOTO 3) else (WAIT=L, STOP) |
1380 | | |
| 1394 | Memory read |
1381 | 1395 | Clock cycles: 2 + W, W = number of wait states |
1382 | 1396 | */ |
1383 | 1397 | void tms99xx_device::mem_read() |
1384 | 1398 | { |
1385 | | // The following line will be taken out of this method and |
1386 | | // be executed at an earlier microprogram clock tick |
1387 | 1399 | // After set_address, any device attached to the address bus may pull down |
1388 | 1400 | // READY in order to put the CPU into wait state before the read_word |
1389 | 1401 | // operation will be performed |
1390 | 1402 | // set_address and read_word should pass the same address as argument |
1391 | | m_prgspace->set_address(m_address & m_prgaddr_mask & 0xfffe); |
| 1403 | if (m_mem_phase==1) |
| 1404 | { |
| 1405 | m_dbin_line(ASSERT_LINE); |
| 1406 | m_prgspace->set_address(m_address & m_prgaddr_mask & 0xfffe); |
| 1407 | m_check_ready = true; |
| 1408 | m_mem_phase = 2; |
| 1409 | m_pass = 2; |
| 1410 | if (VERBOSE>7) LOG("tms99xx: set address bus %04x\n", m_address); |
1392 | 1411 | |
1393 | | m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask & 0xfffe); |
1394 | | pulse_clock(2); |
1395 | | m_check_ready = true; |
1396 | | if (VERBOSE>7) LOG("tms99xx: memory read %04x -> %04x\n", m_address, m_current_value); |
| 1412 | pulse_clock(1); // Concludes the first cycle |
| 1413 | // If READY has been found to be low, the CPU will now stay in the wait state loop |
| 1414 | } |
| 1415 | else |
| 1416 | { |
| 1417 | // Second phase (after READY was raised again) |
| 1418 | m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask & 0xfffe); |
| 1419 | pulse_clock(1); |
| 1420 | m_dbin_line(CLEAR_LINE); |
| 1421 | m_mem_phase = 1; // reset to phase 1 |
| 1422 | if (VERBOSE>7) LOG("tms99xx: memory read %04x -> %04x\n", m_address, m_current_value); |
| 1423 | } |
1397 | 1424 | } |
1398 | 1425 | |
1399 | 1426 | void tms99xx_device::mem_write() |
1400 | 1427 | { |
1401 | | // see mem_read |
1402 | | m_prgspace->set_address(m_address & m_prgaddr_mask & 0xfffe); |
1403 | | |
1404 | | m_prgspace->write_word(m_address & m_prgaddr_mask & 0xfffe, m_current_value); |
1405 | | pulse_clock(2); |
1406 | | m_check_ready = true; |
1407 | | if (VERBOSE>7) LOG("tms99xx: memory write %04x <- %04x\n", m_address, m_current_value); |
| 1428 | if (m_mem_phase==1) |
| 1429 | { |
| 1430 | m_dbin_line(CLEAR_LINE); |
| 1431 | // When writing, the data bus is asserted immediately after the address bus |
| 1432 | if (VERBOSE>7) LOG("tms99xx: set address bus %04x\n", m_address); |
| 1433 | m_prgspace->set_address(m_address & m_prgaddr_mask & 0xfffe); |
| 1434 | if (VERBOSE>7) LOG("tms99xx: memory write %04x <- %04x\n", m_address, m_current_value); |
| 1435 | m_prgspace->write_word(m_address & m_prgaddr_mask & 0xfffe, m_current_value); |
| 1436 | m_check_ready = true; |
| 1437 | m_mem_phase = 2; |
| 1438 | m_pass = 2; |
| 1439 | pulse_clock(1); |
| 1440 | } |
| 1441 | else |
| 1442 | { |
| 1443 | // Second phase (we arrive here when the wait states are over) |
| 1444 | pulse_clock(1); |
| 1445 | } |
1408 | 1446 | } |
1409 | 1447 | |
1410 | 1448 | void tms99xx_device::register_read() |
1411 | 1449 | { |
1412 | 1450 | // Need to set m_address for F1/F3 (we don't know what the data_derive did) |
1413 | | m_address = WP + (m_regnumber<<1); |
| 1451 | if (m_mem_phase==1) |
| 1452 | { |
| 1453 | m_address = WP + (m_regnumber<<1); |
| 1454 | } |
| 1455 | |
1414 | 1456 | mem_read(); |
1415 | | m_check_ready = true; |
1416 | | m_register_contents = m_current_value; |
| 1457 | |
| 1458 | if (m_mem_phase==1) |
| 1459 | { |
| 1460 | m_register_contents = m_current_value; |
| 1461 | } |
1417 | 1462 | } |
1418 | 1463 | |
1419 | 1464 | /* |
1420 | 1465 | Memory write: |
1421 | | 1) Pulse clock |
1422 | | 2) Set address and write (as in the real system) |
1423 | | 3) Pulse clock |
1424 | | 4) If READY=L (WAIT=H, GOTO 3) else (WAIT=L, STOP) |
1425 | 1466 | |
1426 | 1467 | Clock cycles: 2 + W, W = number of wait states |
1427 | 1468 | */ |
1428 | 1469 | void tms99xx_device::register_write() |
1429 | 1470 | { |
| 1471 | // This will be called twice; m_pass is set by the embedded mem_write |
1430 | 1472 | UINT16 addr_save = m_address; |
1431 | 1473 | m_address = (WP + (m_regnumber<<1)) & m_prgaddr_mask & 0xfffe; |
1432 | 1474 | mem_write(); |
1433 | | m_check_ready = true; |
1434 | 1475 | m_address = addr_save; |
1435 | 1476 | } |
1436 | 1477 | |
r25467 | r25468 | |
1530 | 1571 | // Pseudo state at the end of the current instruction cycle sequence |
1531 | 1572 | if (VERBOSE>4) |
1532 | 1573 | { |
1533 | | LOG("tms99xx: +++++ Instruction %04x (%s) completed +++++\n", IR, opname[m_command]); |
| 1574 | LOG("tms99xx: +++++ Instruction %04x (%s) completed", IR, opname[m_command]); |
1534 | 1575 | int cycles = m_first_cycle - m_icount; |
1535 | 1576 | // Avoid nonsense values due to expired and resumed main loop |
1536 | | if (cycles > 0 && cycles < 10000) LOG("tms99xx: Consumed %d cycles\n", cycles); |
| 1577 | if (cycles > 0 && cycles < 10000) LOG(", consumed %d cycles", cycles); |
| 1578 | LOG(" +++++\n"); |
1537 | 1579 | } |
1538 | 1580 | m_program = NULL; |
1539 | | m_lowbyte = false; |
1540 | 1581 | } |
1541 | 1582 | |
1542 | 1583 | /* |