branches/alto2/src/emu/cpu/alto2/a2mem.c
| r26421 | r26422 | |
| 237 | 237 | * Whoa ;-) |
| 238 | 238 | * </PRE> |
| 239 | 239 | */ |
| 240 | | #if ALTO2_HAMMING_CHECK |
| 240 | #if USE_HAMMING_CHECK |
| 241 | 241 | |
| 242 | 242 | #define WD(x) (1ul<<(31-x)) |
| 243 | 243 | |
| r26421 | r26422 | |
| 277 | 277 | /* a74: WD14 WD17 WD18 WD21 WD23 WD24 WD26 WD27 WD29 PCB --- */ |
| 278 | 278 | #define A74 (WD(14)|WD(17)|WD(18)|WD(21)|WD(23)|WD(24)|WD(26)|WD(27)|WD(29)) |
| 279 | 279 | |
| 280 | | #define H0(hpb) X_RDBITS(hpb,8,0,0) //!< get Hamming code bit 0 from hpb data (really bit 32) |
| 281 | | #define H1(hpb) X_RDBITS(hpb,8,1,1) //!< get Hamming code bit 1 from hpb data (really bit 33) |
| 282 | | #define H2(hpb) X_RDBITS(hpb,8,2,2) //!< get Hamming code bit 2 from hpb data (really bit 34) |
| 283 | | #define H3(hpb) X_RDBITS(hpb,8,3,3) //!< get Hamming code bit 3 from hpb data (really bit 35) |
| 284 | | #define H4(hpb) X_RDBITS(hpb,8,4,4) //!< get Hamming code bit 4 from hpb data (really bit 36) |
| 285 | | #define H5(hpb) X_RDBITS(hpb,8,5,5) //!< get Hamming code bit 5 from hpb data (really bit 37) |
| 280 | #define H0(hpb) X_BIT(hpb,8,0) //!< get Hamming code bit 0 from hpb data (really bit 32) |
| 281 | #define H1(hpb) X_BIT(hpb,8,1) //!< get Hamming code bit 1 from hpb data (really bit 33) |
| 282 | #define H2(hpb) X_BIT(hpb,8,2) //!< get Hamming code bit 2 from hpb data (really bit 34) |
| 283 | #define H3(hpb) X_BIT(hpb,8,3) //!< get Hamming code bit 3 from hpb data (really bit 35) |
| 284 | #define H4(hpb) X_BIT(hpb,8,4) //!< get Hamming code bit 4 from hpb data (really bit 36) |
| 285 | #define H5(hpb) X_BIT(hpb,8,5) //!< get Hamming code bit 5 from hpb data (really bit 37) |
| 286 | 286 | #define RH(hpb) X_RDBITS(hpb,8,0,5) //!< get Hamming code from hpb data (bits 32 to 37) |
| 287 | | #define RP(hpb) X_BIT(hpb,8,6) //!< get parity bit from hpb data (really bit 38) |
| 287 | #define RP(hpb) X_BIT(hpb,8,6) //!< get parity bit from hpb data (really bit 38) |
| 288 | 288 | |
| 289 | 289 | /** @brief return even parity of a (masked) 32 bit value */ |
| 290 | 290 | static __inline UINT8 parity_even(UINT32 val) |
| r26421 | r26422 | |
| 440 | 440 | if (perr || syndrome) { |
| 441 | 441 | /* latch data on the first error */ |
| 442 | 442 | if (!m_mem.error) { |
| 443 | | m_mem.error = 1; |
| 443 | m_mem.error = true; |
| 444 | 444 | PUT_MESR_HAMMING(m_mem.mesr, RH(hpb)); |
| 445 | 445 | PUT_MESR_PERR(m_mem.mesr, perr); |
| 446 | 446 | PUT_MESR_PARITY(m_mem.mesr, RP(hpb)); |
| r26421 | r26422 | |
| 480 | 480 | } |
| 481 | 481 | return dw_data; |
| 482 | 482 | } |
| 483 | | #endif /* ALTO2_HAMMING_CHECK */ |
| 483 | #endif /* USE_HAMMING_CHECK */ |
| 484 | 484 | |
| 485 | 485 | /** |
| 486 | 486 | * @brief memory error address register read |
| r26421 | r26422 | |
| 524 | 524 | LOG((LOG_MEM,6," Hamming code read : %#o\n", GET_MESR_HAMMING(data))); |
| 525 | 525 | LOG((LOG_MEM,6," Parity error : %o\n", GET_MESR_PERR(data))); |
| 526 | 526 | LOG((LOG_MEM,6," Memory parity bit : %o\n", GET_MESR_PARITY(data))); |
| 527 | | #if ALTO2_HAMMING_CHECK |
| 527 | #if USE_HAMMING_CHECK |
| 528 | 528 | LOG((LOG_MEM,6," Hamming syndrome : %#o (bit #%d)\n", GET_MESR_SYNDROME(data), hamming_lut[GET_MESR_SYNDROME(data)])); |
| 529 | 529 | #else |
| 530 | 530 | LOG((LOG_MEM,6," Hamming syndrome : %#o\n", GET_MESR_SYNDROME(data))); |
| r26421 | r26422 | |
| 641 | 641 | // keep track of the current CPU cycle |
| 642 | 642 | m_mem.cycle = cycle(); |
| 643 | 643 | } else { |
| 644 | | m_mem.access = ALTO2_MEM_NIRVANA; |
| 644 | m_mem.access = ALTO2_MEM_INVALID; |
| 645 | 645 | m_mem.rmdd = m_mem.wmdd = ~0; |
| 646 | 646 | } |
| 647 | 647 | } |
| r26421 | r26422 | |
| 677 | 677 | return m_mem.md; |
| 678 | 678 | } |
| 679 | 679 | |
| 680 | | #if ALTO2_HAMMING_CHECK |
| 680 | #if USE_HAMMING_CHECK |
| 681 | 681 | /* check for errors on the first access */ |
| 682 | 682 | if (!(m_mem.access & ALTO2_MEM_ODD)) |
| 683 | 683 | m_mem.rmdd = hamming_code(0, m_mem.mar/2, m_mem.rmdd); |
| r26421 | r26422 | |
| 740 | 740 | else |
| 741 | 741 | PUT_EVEN(m_mem.wmdd, m_mem.md); |
| 742 | 742 | |
| 743 | | #if ALTO2_HAMMING_CHECK |
| 743 | #if USE_HAMMING_CHECK |
| 744 | 744 | if (m_mem.access & ALTO2_MEM_RAM) |
| 745 | 745 | m_mem.ram[m_mem.mar/2] = hamming_code(1, m_mem.mar/2, m_mem.wmdd); |
| 746 | 746 | #else |
| r26421 | r26422 | |
| 855 | 855 | m_mem.ram = auto_alloc_array_clear(machine(), UINT32, sizeof(UINT16) * m_mem.size); |
| 856 | 856 | m_mem.hpb = auto_alloc_array_clear(machine(), UINT8, sizeof(UINT16) * m_mem.size); |
| 857 | 857 | |
| 858 | | #if ALTO2_HAMMING_CHECK |
| 858 | #if USE_HAMMING_CHECK |
| 859 | 859 | // Initialize the hamming codes and parity bit |
| 860 | 860 | for (UINT32 addr = 0; addr < ALTO2_IO_PAGE_BASE; addr++) { |
| 861 | 861 | hamming_code(1, addr, 0); |
| r26421 | r26422 | |
| 868 | 868 | m_mem.md = 0; |
| 869 | 869 | m_mem.cycle = 0; |
| 870 | 870 | m_mem.access = 0; |
| 871 | | m_mem.error = 0; |
| 871 | m_mem.error = false; |
| 872 | 872 | m_mem.mear = 0; |
| 873 | 873 | m_mem.mesr = 0; |
| 874 | 874 | m_mem.mecr = 0; |
branches/alto2/src/emu/cpu/alto2/a2disk.c
| r26421 | r26422 | |
| 346 | 346 | #define WDALLOW (!GET_KCOM_WDINHIB(m_dsk.kcom)) |
| 347 | 347 | #define WDINIT ((m_dsk.ff_53b & JKFF_Q) ? 1 : 0) |
| 348 | 348 | #define RDYLAT ((m_dsk.ff_45a & JKFF_Q) ? 1 : 0) |
| 349 | | #define SEQERR ((m_task == task_ksec && m_dsk.seclate == 0) || (m_task == task_kwd && m_dsk.carry == 1)) |
| 349 | #define SEQERR ((m_task == task_ksec && m_dsk.seclate == 0) || (m_task == task_kwd && m_dsk.bitcount == 15)) |
| 350 | 350 | #define ERRWAKE (RDYLAT | m_dsk.ready_mf31a) |
| 351 | 351 | #define SEEKOK (m_dsk.seekok) |
| 352 | 352 | |
| r26421 | r26422 | |
| 366 | 366 | int i; |
| 367 | 367 | UINT8 s0, s1; |
| 368 | 368 | |
| 369 | | LOG((LOG_DISK,8," *** KWD timing bitclk:%d datin:%d block:%d\n", bitclk, datin, block)); |
| 370 | | if (0 == m_dsk.seclate) { |
| 369 | LOG((LOG_DISK,9," *** KWD timing bitclk:%d datin:%d block:%d\n", bitclk, datin, block)); |
| 370 | if (0 == m_dsk.seclate) |
| 371 | { |
| 371 | 372 | // if SECLATE is 0, WDDONE' never goes low (counter's clear has precedence). |
| 372 | | if (m_dsk.bitcount || m_dsk.carry) { |
| 373 | if (m_dsk.bitcount) { |
| 373 | 374 | LOG((LOG_DISK,7," SECLATE:0 clears bitcount:0\n")); |
| 374 | 375 | m_dsk.bitcount = 0; |
| 375 | | m_dsk.carry = 0; |
| 376 | 376 | } |
| 377 | | } else if (m_dsk.bitclk && !bitclk) { |
| 378 | | // if SECLATE is 1, the counter will count or be loaded |
| 379 | | if ((m_dsk.shiftin & (1 << 16)) && !GET_KCOM_WFFO(m_dsk.kcom)) { |
| 377 | } |
| 378 | else |
| 379 | { |
| 380 | // SECLATE is 1 |
| 381 | if (m_dsk.bitclk && !bitclk) |
| 382 | { |
| 383 | // on the falling edge of bitclk the counter will count or be loaded |
| 384 | if ((m_dsk.shiftin & (1 << 16)) && !GET_KCOM_WFFO(m_dsk.kcom)) { |
| 385 | /* |
| 386 | * If HIORDBIT is 1 at the falling edge of BITCLK, it sets the |
| 387 | * JK-FF 67b, and thus takes away the LOAD' assertion from the |
| 388 | * counter. It has been loaded with 15, so it counts to 16 on |
| 389 | * the next rising edge and makes WDDONE' go to 0. |
| 390 | */ |
| 391 | LOG((LOG_DISK,7," HIORDBIT:1 sets WFFO:1\n")); |
| 392 | PUT_KCOM_WFFO(m_dsk.kcom, 1); |
| 393 | // TODO: show disk indicators |
| 394 | } |
| 380 | 395 | /* |
| 381 | | * If HIORDBIT is 1 at the falling edge of BITCLK, it sets the |
| 382 | | * JK-FF 67b, and thus takes away the LOAD' assertion from the |
| 383 | | * counter. It has been loaded with 15, so it counts to 16 on |
| 384 | | * the next rising edge and makes WDDONE' go to 0. |
| 396 | * Falling edge of BITCLK, counting continues as it was preset |
| 397 | * with BUS[4] (WFFO) at the last KCOM← load, or as set by a |
| 398 | * 1 bit being read in HIORDBIT. |
| 385 | 399 | */ |
| 386 | | LOG((LOG_DISK,7," HIORDBIT:1 sets WFFO:1\n")); |
| 387 | | PUT_KCOM_WFFO(m_dsk.kcom, 1); |
| 388 | | // TODO: show disk indicators |
| 400 | if (GET_KCOM_WFFO(m_dsk.kcom)) { |
| 401 | /* |
| 402 | * If BUS[4] (WFFO) was 1, both J and K' of the FF (74109) will |
| 403 | * be 1 at the rising edge of LDCOM' (at the end of KCOM←) |
| 404 | * and Q will be 1. LOAD' is deassterted: count on clock. |
| 405 | */ |
| 406 | m_dsk.bitcount = (m_dsk.bitcount + 1) % 16; |
| 407 | LOG((LOG_DISK,6," WFFO:1 count bitcount:%2d\n", m_dsk.bitcount)); |
| 408 | } else { |
| 409 | /* |
| 410 | * If BUS[4] (WFFO) was 0, both J and K' will be 0, and Q |
| 411 | * will be 0. LOAD' is asserted and will load on rising bitclock (now) |
| 412 | */ |
| 413 | m_dsk.bitcount = 15; |
| 414 | LOG((LOG_DISK,6," WFFO:0 load bitcount:%2d\n", m_dsk.bitcount)); |
| 415 | } |
| 389 | 416 | } |
| 390 | | /* |
| 391 | | * Falling edge of BITCLK, counting continues as it was preset |
| 392 | | * with BUS[4] (WFFO) at the last KCOM← load, or as set by a |
| 393 | | * 1 bit being read in HIORDBIT. |
| 394 | | */ |
| 395 | | if (GET_KCOM_WFFO(m_dsk.kcom)) { |
| 396 | | /* |
| 397 | | * If BUS[4] (WFFO) was 1, both J and K' of the FF (74109) will |
| 398 | | * be 1 at the rising edge of LDCOM' (at the end of KCOM←) |
| 399 | | * and Q will be 1. LOAD' is deassterted: count on clock. |
| 400 | | */ |
| 401 | | m_dsk.bitcount = (m_dsk.bitcount + 1) % 16; |
| 402 | | m_dsk.carry = m_dsk.bitcount == 15; |
| 403 | | LOG((LOG_DISK,6," WFFO:1 count bitcount:%2d\n", m_dsk.bitcount)); |
| 404 | | } else { |
| 405 | | /* |
| 406 | | * If BUS[4] (WFFO) was 0, both J and K' will be 0, and Q |
| 407 | | * will be 0. LOAD' is asserted and will load on rising bitclock (now) |
| 408 | | */ |
| 409 | | m_dsk.bitcount = 15; |
| 410 | | m_dsk.carry = 1; |
| 411 | | LOG((LOG_DISK,6," WFFO:0 load bitcount:%2d\n", m_dsk.bitcount)); |
| 417 | if (!m_dsk.bitclk && bitclk) { |
| 418 | // rising edge of bitclk |
| 419 | m_dsk.shiftin = (m_dsk.shiftin << 1) | datin; // clock the input shift register |
| 420 | m_dsk.shiftout = m_dsk.shiftout << 1; // and the output shift register too |
| 412 | 421 | } |
| 413 | | } else if (!m_dsk.bitclk && bitclk) { |
| 414 | | // rising edge of bitclk |
| 415 | | m_dsk.shiftin = (m_dsk.shiftin << 1) | datin; // clock the input shift register |
| 416 | | m_dsk.shiftout = m_dsk.shiftout << 1; // and the output shift register too |
| 417 | 422 | } |
| 418 | 423 | |
| 419 | 424 | if (m_dsk.wddone != wddone) { |
| 420 | 425 | LOG((LOG_DISK,8," WDDONE':%d→%d\n", m_dsk.wddone, wddone)); |
| 421 | 426 | } |
| 422 | 427 | |
| 423 | | if (m_dsk.carry) { |
| 428 | if (15 == m_dsk.bitcount) { |
| 424 | 429 | /* CARRY = 1 -> WDDONE' = 0 */ |
| 425 | 430 | wddone = 0; |
| 426 | 431 | if (m_dsk.wddone == 0) { |
| r26421 | r26422 | |
| 1368 | 1373 | s1 |= JKFF_C; |
| 1369 | 1374 | m_dsk.ff_43a = update_jkff(s0, s1, "43a KWD "); |
| 1370 | 1375 | |
| 1371 | | if (m_dsk.ff_43a & JKFF_Q) { |
| 1372 | | m_dsk.wdtskena = 1; |
| 1373 | | m_task_wakeup &= ~(1 << task_kwd); |
| 1374 | | } |
| 1376 | m_dsk.wdtskena = 1; |
| 1377 | m_task_wakeup &= ~(1 << task_kwd); |
| 1375 | 1378 | } |
| 1376 | 1379 | } |
| 1377 | 1380 | // TODO: show disk indicator in the GUI? |
| r26421 | r26422 | |
| 1422 | 1425 | } |
| 1423 | 1426 | |
| 1424 | 1427 | /** |
| 1425 | | * @brief f2_init late: branch on disk word task active and init |
| 1428 | * @brief branch on disk word task active and init |
| 1426 | 1429 | * |
| 1427 | 1430 | * NEXT ← NEXT OR (WDTASKACT && WDINIT ? 037 : 0) |
| 1428 | 1431 | */ |
| r26421 | r26422 | |
| 1436 | 1439 | } |
| 1437 | 1440 | |
| 1438 | 1441 | /** |
| 1439 | | * @brief f2_rwc late: branch on read/write/check state of the current record |
| 1442 | * @brief branch on read/write/check state of the current record |
| 1440 | 1443 | * <PRE> |
| 1441 | 1444 | * NEXT ← NEXT OR (current record to be written ? 3 : current record to be checked ? 2 : 0); |
| 1442 | 1445 | * |
| r26421 | r26422 | |
| 1463 | 1466 | UINT16 init = (m_task == task_kwd && m_dsk.wdinit0) ? 037 : 0; |
| 1464 | 1467 | |
| 1465 | 1468 | switch (m_dsk.krwc & 3) { |
| 1466 | | case 0: |
| 1469 | case 0: // read |
| 1467 | 1470 | r = 0; |
| 1468 | 1471 | break; |
| 1469 | | case 1: |
| 1472 | case 1: // check |
| 1470 | 1473 | r = 2; |
| 1471 | 1474 | break; |
| 1472 | | default: |
| 1475 | default: // write |
| 1473 | 1476 | r = 3; |
| 1474 | 1477 | } |
| 1475 | 1478 | |
| r26421 | r26422 | |
| 1520 | 1523 | } |
| 1521 | 1524 | |
| 1522 | 1525 | /** |
| 1523 | | * @brief f2_xfrdat late: branch on the data transfer state |
| 1526 | * @brief branch on the data transfer state |
| 1524 | 1527 | * |
| 1525 | 1528 | * NEXT ← NEXT OR (if current command wants data transfer ? 1 : 0) |
| 1526 | 1529 | */ |
| r26421 | r26422 | |
| 1534 | 1537 | } |
| 1535 | 1538 | |
| 1536 | 1539 | /** |
| 1537 | | * @brief f2_swrnrdy late: branch on the disk ready signal |
| 1540 | * @brief branch on the disk ready signal |
| 1538 | 1541 | * |
| 1539 | 1542 | * NEXT ← NEXT OR (if disk not ready to accept command ? 1 : 0) |
| 1540 | 1543 | */ |
| r26421 | r26422 | |
| 1550 | 1553 | } |
| 1551 | 1554 | |
| 1552 | 1555 | /** |
| 1553 | | * @brief f2_nfer late: branch on the disk fatal error condition |
| 1556 | * @brief branch on the disk fatal error condition |
| 1554 | 1557 | * |
| 1555 | 1558 | * NEXT ← NEXT OR (if fatal error in latches ? 0 : 1) |
| 1556 | 1559 | */ |
| r26421 | r26422 | |
| 1624 | 1627 | } else { |
| 1625 | 1628 | bit = (m_dsk.shiftout >> 15) & 1; |
| 1626 | 1629 | kwd_timing(clk, bit, 0); |
| 1627 | | LOG((LOG_DISK,7," BITCLK#%d bit:%d (write) @%lldns\n", arg, bit, ntime())); |
| 1630 | LOG((LOG_DISK,8," BITCLK#%d bit:%d (write) @%lldns\n", arg, bit, ntime())); |
| 1628 | 1631 | if (clk) |
| 1629 | 1632 | dhd->wr_data(arg, bit); |
| 1630 | 1633 | else |
| r26421 | r26422 | |
| 1633 | 1636 | } else if (GET_KCOM_BCLKSRC(m_dsk.kcom)) { |
| 1634 | 1637 | /* always select the crystal clock */ |
| 1635 | 1638 | bit = dhd->rd_data(arg); |
| 1636 | | LOG((LOG_DISK,7," BITCLK#%d bit:%d (read, crystal) @%lldns\n", arg, bit, ntime())); |
| 1639 | LOG((LOG_DISK,8," BITCLK#%d bit:%d (read, crystal) @%lldns\n", arg, bit, ntime())); |
| 1637 | 1640 | kwd_timing(clk, bit, 0); |
| 1638 | 1641 | } else { |
| 1639 | 1642 | /* if XFEROFF is set, keep the bit at 1 (RDGATE' is high) */ |
| r26421 | r26422 | |
| 1642 | 1645 | } else { |
| 1643 | 1646 | clk = dhd->rd_clock(arg); |
| 1644 | 1647 | bit = dhd->rd_data(arg); |
| 1645 | | LOG((LOG_DISK,7," BITCLK#%d bit:%d (read, driveclk) @%lldns\n", arg, bit, ntime())); |
| 1648 | LOG((LOG_DISK,8," BITCLK#%d bit:%d (read, driveclk) @%lldns\n", arg, bit, ntime())); |
| 1646 | 1649 | } |
| 1647 | 1650 | kwd_timing(clk, bit, 0); |
| 1648 | 1651 | } |
| r26421 | r26422 | |
| 1728 | 1731 | void alto2_cpu_device::init_disk() |
| 1729 | 1732 | { |
| 1730 | 1733 | memset(&m_dsk, 0, sizeof(m_dsk)); |
| 1734 | save_item(NAME(m_dsk.drive)); |
| 1735 | save_item(NAME(m_dsk.kaddr)); |
| 1736 | save_item(NAME(m_dsk.kadr)); |
| 1737 | save_item(NAME(m_dsk.kstat)); |
| 1738 | save_item(NAME(m_dsk.kcom)); |
| 1739 | save_item(NAME(m_dsk.krecno)); |
| 1740 | save_item(NAME(m_dsk.shiftin)); |
| 1741 | save_item(NAME(m_dsk.shiftout)); |
| 1742 | save_item(NAME(m_dsk.datain)); |
| 1743 | save_item(NAME(m_dsk.dataout)); |
| 1744 | save_item(NAME(m_dsk.krwc)); |
| 1745 | save_item(NAME(m_dsk.kfer)); |
| 1746 | save_item(NAME(m_dsk.wdtskena)); |
| 1747 | save_item(NAME(m_dsk.wdinit0)); |
| 1748 | save_item(NAME(m_dsk.wdinit)); |
| 1749 | save_item(NAME(m_dsk.strobe)); |
| 1750 | save_item(NAME(m_dsk.bitclk)); |
| 1751 | save_item(NAME(m_dsk.datin)); |
| 1752 | save_item(NAME(m_dsk.bitcount)); |
| 1753 | save_item(NAME(m_dsk.carry)); |
| 1754 | save_item(NAME(m_dsk.seclate)); |
| 1755 | save_item(NAME(m_dsk.seekok)); |
| 1756 | save_item(NAME(m_dsk.ok_to_run)); |
| 1757 | save_item(NAME(m_dsk.ready_mf31a)); |
| 1758 | save_item(NAME(m_dsk.seclate_mf31b)); |
| 1759 | #if 0 |
| 1760 | save_item(NAME(m_dsk.ff_21a)); |
| 1761 | save_item(NAME(m_dsk.ff_21a_old)); |
| 1762 | save_item(NAME(m_dsk.ff_21b)); |
| 1763 | save_item(NAME(m_dsk.ff_22a)); |
| 1764 | save_item(NAME(m_dsk.ff_22b)); |
| 1765 | save_item(NAME(m_dsk.ff_43b)); |
| 1766 | save_item(NAME(m_dsk.ff_53a)); |
| 1767 | save_item(NAME(m_dsk.ff_43a)); |
| 1768 | save_item(NAME(m_dsk.ff_53b)); |
| 1769 | save_item(NAME(m_dsk.ff_44a)); |
| 1770 | save_item(NAME(m_dsk.ff_44b)); |
| 1771 | save_item(NAME(m_dsk.ff_45a)); |
| 1772 | save_item(NAME(m_dsk.ff_45b)); |
| 1773 | #endif |
| 1731 | 1774 | |
| 1732 | 1775 | /** @brief simulate previous sysclka */ |
| 1733 | 1776 | m_sysclka0[0] = JKFF_CLK; |
| r26421 | r26422 | |
| 1823 | 1866 | #endif |
| 1824 | 1867 | m_dsk.datin = 0; |
| 1825 | 1868 | m_dsk.bitcount = 0; |
| 1826 | | m_dsk.carry = 0; |
| 1827 | 1869 | m_dsk.seclate = 0; |
| 1828 | 1870 | m_dsk.seclate_timer->reset(); |
| 1829 | 1871 | m_dsk.seekok = 0; |
branches/alto2/src/emu/cpu/alto2/alto2cpu.c
| r26421 | r26422 | |
| 149 | 149 | m_icount(0), |
| 150 | 150 | m_task_mpc(), |
| 151 | 151 | m_task_next2(), |
| 152 | | m_pico_time(), |
| 153 | 152 | m_task(0), |
| 154 | 153 | m_next_task(0), |
| 155 | 154 | m_next2_task(0), |
| r26421 | r26422 | |
| 848 | 847 | #endif |
| 849 | 848 | save_item(NAME(m_task_mpc)); |
| 850 | 849 | save_item(NAME(m_task_next2)); |
| 851 | | save_item(NAME(m_pico_time)); |
| 852 | 850 | save_item(NAME(m_task)); |
| 853 | 851 | save_item(NAME(m_next_task)); |
| 854 | 852 | save_item(NAME(m_next2_task)); |
| r26421 | r26422 | |
| 888 | 886 | save_item(NAME(m_mouse.dx)); |
| 889 | 887 | save_item(NAME(m_mouse.dy)); |
| 890 | 888 | save_item(NAME(m_mouse.latch)); |
| 891 | | save_item(NAME(m_dsk.drive)); |
| 892 | | save_item(NAME(m_dsk.kaddr)); |
| 893 | | save_item(NAME(m_dsk.kadr)); |
| 894 | | save_item(NAME(m_dsk.kstat)); |
| 895 | | save_item(NAME(m_dsk.kcom)); |
| 896 | | save_item(NAME(m_dsk.krecno)); |
| 897 | | save_item(NAME(m_dsk.shiftin)); |
| 898 | | save_item(NAME(m_dsk.shiftout)); |
| 899 | | save_item(NAME(m_dsk.datain)); |
| 900 | | save_item(NAME(m_dsk.dataout)); |
| 901 | | save_item(NAME(m_dsk.krwc)); |
| 902 | | save_item(NAME(m_dsk.kfer)); |
| 903 | | save_item(NAME(m_dsk.wdtskena)); |
| 904 | | save_item(NAME(m_dsk.wdinit0)); |
| 905 | | save_item(NAME(m_dsk.wdinit)); |
| 906 | | save_item(NAME(m_dsk.strobe)); |
| 907 | | save_item(NAME(m_dsk.bitclk)); |
| 908 | | save_item(NAME(m_dsk.datin)); |
| 909 | | save_item(NAME(m_dsk.bitcount)); |
| 910 | | save_item(NAME(m_dsk.carry)); |
| 911 | | save_item(NAME(m_dsk.seclate)); |
| 912 | | save_item(NAME(m_dsk.seekok)); |
| 913 | | save_item(NAME(m_dsk.ok_to_run)); |
| 914 | | save_item(NAME(m_dsk.ready_mf31a)); |
| 915 | | save_item(NAME(m_dsk.seclate_mf31b)); |
| 916 | | #if 0 |
| 917 | | save_item(NAME(m_dsk.ff_21a)); |
| 918 | | save_item(NAME(m_dsk.ff_21a_old)); |
| 919 | | save_item(NAME(m_dsk.ff_21b)); |
| 920 | | save_item(NAME(m_dsk.ff_22a)); |
| 921 | | save_item(NAME(m_dsk.ff_22b)); |
| 922 | | save_item(NAME(m_dsk.ff_43b)); |
| 923 | | save_item(NAME(m_dsk.ff_53a)); |
| 924 | | save_item(NAME(m_dsk.ff_43a)); |
| 925 | | save_item(NAME(m_dsk.ff_53b)); |
| 926 | | save_item(NAME(m_dsk.ff_44a)); |
| 927 | | save_item(NAME(m_dsk.ff_44b)); |
| 928 | | save_item(NAME(m_dsk.ff_45a)); |
| 929 | | save_item(NAME(m_dsk.ff_45b)); |
| 930 | | #endif |
| 931 | 889 | |
| 932 | 890 | hard_reset(); |
| 933 | 891 | |
| r26421 | r26422 | |
| 1501 | 1459 | if (m_d_f2 != f2_emu_load_dns) { |
| 1502 | 1460 | m_r[m_rsel] = m_shifter; |
| 1503 | 1461 | LOG((LOG_CPU,2," R%02o←; %s = SHIFTER (%#o)\n", m_rsel, r_name(m_rsel), m_shifter)); |
| 1504 | | #if 1 |
| 1462 | #if 0 |
| 1505 | 1463 | /* HACK: programs writing r37 with xxx3 make the cursor |
| 1506 | 1464 | * display go nuts. Until I found the real reason for this |
| 1507 | 1465 | * obviously buggy display, I just clear the two |
| r26421 | r26422 | |
| 1851 | 1809 | } |
| 1852 | 1810 | |
| 1853 | 1811 | /** |
| 1854 | | * @brief f1_block early: block task |
| 1812 | * @brief block task |
| 1855 | 1813 | * |
| 1856 | | * The task request for the active task is cleared |
| 1814 | * The task wakeup for the active task is cleared |
| 1857 | 1815 | */ |
| 1858 | 1816 | void alto2_cpu_device::f1_early_block() |
| 1859 | 1817 | { |
| r26421 | r26422 | |
| 1861 | 1819 | LOG((LOG_CPU,2, " BLOCK %02o:%s\n", m_task, task_name(m_task))); |
| 1862 | 1820 | } |
| 1863 | 1821 | |
| 1822 | /** |
| 1823 | * @brief SHIFTER = L shifted left once |
| 1824 | */ |
| 1864 | 1825 | void alto2_cpu_device::f1_late_l_lsh_1() |
| 1865 | 1826 | { |
| 1866 | 1827 | m_shifter = m_l << 1; |
| 1867 | 1828 | LOG((LOG_CPU,2," SHIFTER ←L LSH 1 (%#o := %#o<<1)\n", m_shifter, m_l)); |
| 1868 | 1829 | } |
| 1869 | 1830 | |
| 1831 | /** |
| 1832 | * @brief SHIFTER = L shifted right once |
| 1833 | */ |
| 1870 | 1834 | void alto2_cpu_device::f1_late_l_rsh_1() |
| 1871 | 1835 | { |
| 1872 | 1836 | m_shifter = m_l >> 1; |
| 1873 | 1837 | LOG((LOG_CPU,2," SHIFTER ←L RSH 1 (%#o := %#o>>1)\n", m_shifter, m_l)); |
| 1874 | 1838 | } |
| 1875 | 1839 | |
| 1840 | /** |
| 1841 | * @brief SHIFTER = L cycled 8 times (byte swap) |
| 1842 | */ |
| 1876 | 1843 | void alto2_cpu_device::f1_late_l_lcy_8() |
| 1877 | 1844 | { |
| 1878 | 1845 | m_shifter = (m_l >> 8) | (m_l << 8); |
| r26421 | r26422 | |
| 1890 | 1857 | } |
| 1891 | 1858 | |
| 1892 | 1859 | /** |
| 1893 | | * @brief f2_shifter_lt_zero late: branch on shifter less than zero |
| 1860 | * @brief branch on shifter less than zero |
| 1894 | 1861 | */ |
| 1895 | 1862 | void alto2_cpu_device::f2_late_shifter_lt_zero() |
| 1896 | 1863 | { |
| r26421 | r26422 | |
| 1900 | 1867 | } |
| 1901 | 1868 | |
| 1902 | 1869 | /** |
| 1903 | | * @brief f2_shifter_eq_zero late: branch on shifter equals zero |
| 1870 | * @brief branch on shifter equals zero |
| 1904 | 1871 | */ |
| 1905 | 1872 | void alto2_cpu_device::f2_late_shifter_eq_zero() |
| 1906 | 1873 | { |
| r26421 | r26422 | |
| 2302 | 2269 | m_d_loadl = X_BIT(m_mir, 32, DLOADL); |
| 2303 | 2270 | |
| 2304 | 2271 | debugger_instruction_hook(this, m_mpc); |
| 2305 | | |
| 2306 | 2272 | m_cycle++; |
| 2307 | | m_pico_time[m_task] += ALTO2_UCYCLE; // add per task pico seconds per cycle |
| 2308 | 2273 | |
| 2309 | | /* |
| 2310 | | * This bus source decoding is not performed if f1 == f1_const |
| 2311 | | * or f2 == f2_const. These functions use the MIR BS field to |
| 2312 | | * provide a part of the address to the constant ROM instead. |
| 2313 | | */ |
| 2314 | | do_bs = !(m_d_f1 == f1_const || m_d_f2 == f2_const); |
| 2315 | 2274 | |
| 2316 | 2275 | if (m_d_f1 == f1_load_mar && check_mem_load_mar_stall(m_rsel)) { |
| 2317 | 2276 | LOG((LOG_CPU,3, " MAR← stall\n")); |
| r26421 | r26422 | |
| 2321 | 2280 | LOG((LOG_CPU,3, " MD← stall\n")); |
| 2322 | 2281 | continue; |
| 2323 | 2282 | } |
| 2283 | /* |
| 2284 | * Bus source decoding is not performed if f1 == f1_const |
| 2285 | * or f2 == f2_const. These functions use the MIR BS field to |
| 2286 | * provide a part of the address to the constant ROM instead. |
| 2287 | */ |
| 2288 | do_bs = !(m_d_f1 == f1_const || m_d_f2 == f2_const); |
| 2324 | 2289 | if (do_bs && m_d_bs == bs_read_md && check_mem_read_stall()) { |
| 2325 | 2290 | LOG((LOG_CPU,3, " ←MD stall\n")); |
| 2326 | 2291 | continue; |
| r26421 | r26422 | |
| 2572 | 2537 | alu = m_bus; |
| 2573 | 2538 | m_aluc0 = 1; |
| 2574 | 2539 | flags = ALUM | TSELECT; |
| 2575 | | LOG((LOG_CPU,0," ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, aluf)); |
| 2540 | LOG((LOG_CPU,0," ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, m_d_aluf)); |
| 2576 | 2541 | break; |
| 2577 | 2542 | |
| 2578 | 2543 | /** |
| r26421 | r26422 | |
| 2586 | 2551 | alu = m_bus; |
| 2587 | 2552 | m_aluc0 = 1; |
| 2588 | 2553 | flags = ALUM | TSELECT; |
| 2589 | | LOG((LOG_CPU,0," ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, aluf)); |
| 2554 | LOG((LOG_CPU,0," ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, m_d_aluf)); |
| 2590 | 2555 | } |
| 2591 | 2556 | m_alu = static_cast<UINT16>(alu); |
| 2592 | 2557 | #endif |
branches/alto2/src/emu/cpu/alto2/alto2cpu.h
| r26421 | r26422 | |
| 53 | 53 | #define ALTO2_FAKE_STATUS_H 12 //!< number of extra scanlines to display some status info |
| 54 | 54 | |
| 55 | 55 | #define USE_PRIO_F9318 0 //!< define to 1 to use the F9318 priority encoder code |
| 56 | | #define USE_ALU_74181 1 //!< define to 1 to use the SN74181 ALU code |
| 56 | #define USE_ALU_74181 0 //!< define to 1 to use the SN74181 ALU code |
| 57 | 57 | #define USE_BITCLK_TIMER 0 //!< define to 1 to use a very high rate timer for the disk bit clock |
| 58 | | #define ALTO2_HAMMING_CHECK 0 //!< define to 1 to incorporate the Hamming code and Parity check |
| 58 | #define USE_HAMMING_CHECK 1 //!< define to 1 to use the Hamming code and Parity check in a2mem |
| 59 | 59 | |
| 60 | 60 | #define ALTO2_TASKS 16 //!< 16 task slots |
| 61 | 61 | #define ALTO2_REGS 32 //!< 32 16-bit words in the R register file |
| r26421 | r26422 | |
| 445 | 445 | bs_task_4, //!< BUS source is task specific |
| 446 | 446 | bs_read_md, //!< BUS source is memory data |
| 447 | 447 | bs_mouse, //!< BUS source is mouse data |
| 448 | | bs_disp, //!< BUS source displacement |
| 448 | bs_disp //!< BUS source displacement (emulator task) |
| 449 | 449 | }; |
| 450 | 450 | |
| 451 | 451 | //! Function 1 numbers |
| r26421 | r26422 | |
| 453 | 453 | f1_nop, //!< f1 00 no operation |
| 454 | 454 | f1_load_mar, //!< f1 01 load memory address register |
| 455 | 455 | f1_task, //!< f1 02 task switch |
| 456 | | f1_block, //!< f1 03 block task |
| 456 | f1_block, //!< f1 03 task block |
| 457 | 457 | f1_l_lsh_1, //!< f1 04 left shift L once |
| 458 | 458 | f1_l_rsh_1, //!< f1 05 right shift L once |
| 459 | 459 | f1_l_lcy_8, //!< f1 06 cycle L 8 times |
| r26421 | r26422 | |
| 466 | 466 | f1_task_14, //!< f1 14 task specific |
| 467 | 467 | f1_task_15, //!< f1 15 task specific |
| 468 | 468 | f1_task_16, //!< f1 16 task specific |
| 469 | | f1_task_17, //!< f1 17 task specific |
| 469 | f1_task_17 //!< f1 17 task specific |
| 470 | 470 | }; |
| 471 | 471 | |
| 472 | 472 | //! Function 2 numbers |
| r26421 | r26422 | |
| 487 | 487 | f2_task_14, //!< f2 14 task specific |
| 488 | 488 | f2_task_15, //!< f2 15 task specific |
| 489 | 489 | f2_task_16, //!< f2 16 task specific |
| 490 | | f2_task_17, //!< f2 17 task specific |
| 490 | f2_task_17 //!< f2 17 task specific |
| 491 | 491 | }; |
| 492 | 492 | |
| 493 | 493 | //! enumeration of the micro code word bits |
| r26421 | r26422 | |
| 526 | 526 | |
| 527 | 527 | UINT16 m_task_mpc[ALTO2_TASKS]; //!< per task micro program counter |
| 528 | 528 | UINT16 m_task_next2[ALTO2_TASKS]; //!< per task address modifier |
| 529 | | attoseconds_t m_pico_time[ALTO2_TASKS]; //!< per task atto seconds executed |
| 530 | 529 | UINT8 m_task; //!< active task |
| 531 | 530 | UINT8 m_next_task; //!< next micro instruction's task |
| 532 | 531 | UINT8 m_next2_task; //!< next but one micro instruction's task |