trunk/src/emu/cpu/tms0980/tms0980.c
| r23640 | r23641 | |
| 125 | 125 | |
| 126 | 126 | #define LOG 0 |
| 127 | 127 | |
| 128 | |
| 129 | const device_type TMS0980 = &device_creator<tms0980_cpu_device>; |
| 130 | const device_type TMS1000 = &device_creator<tms1000_cpu_device>; |
| 131 | const device_type TMS1070 = &device_creator<tms1070_cpu_device>; |
| 132 | const device_type TMS1200 = &device_creator<tms1200_cpu_device>; |
| 133 | const device_type TMS1270 = &device_creator<tms1270_cpu_device>; |
| 134 | const device_type TMS1100 = &device_creator<tms1100_cpu_device>; |
| 135 | const device_type TMS1300 = &device_creator<tms1300_cpu_device>; |
| 136 | |
| 137 | |
| 128 | 138 | #define MICRO_MASK 0x80000000 |
| 129 | 139 | #define FIXED_INSTRUCTION 0x00000000 |
| 130 | 140 | |
| r23640 | r23641 | |
| 226 | 236 | #define I_YNEC ( MICRO_MASK | M_YTP | M_CKN | M_NE ) |
| 227 | 237 | |
| 228 | 238 | |
| 229 | | struct tms0980_state |
| 230 | | { |
| 231 | | UINT8 m_prev_pc; /* previous program counter */ |
| 232 | | UINT8 m_prev_pa; /* previous page address register */ |
| 233 | | UINT8 m_pc; /* program counter is a 7 bit register on tms0980, 6 bit register on tms1000/1070/1200/1270/1100/1300 */ |
| 234 | | UINT8 m_pa; /* page address register is a 4 bit register */ |
| 235 | | UINT8 m_sr; /* subroutine return register is a 7 bit register */ |
| 236 | | UINT8 m_pb; /* page buffer register is a 4 bit register */ |
| 237 | | UINT8 m_a; /* Accumulator is a 4 bit register (?) */ |
| 238 | | UINT8 m_x; /* X-register is a 2, 3, or 4 bit register */ |
| 239 | | UINT8 m_y; /* Y-register is a 4 bit register */ |
| 240 | | UINT8 m_dam; /* DAM register is a 4 bit register */ |
| 241 | | UINT8 m_ca; /* Chapter address bit */ |
| 242 | | UINT8 m_cb; /* Chapter buffer bit */ |
| 243 | | UINT8 m_cs; /* Chapter subroutine bit */ |
| 244 | | UINT16 m_r; |
| 245 | | UINT8 m_o; |
| 246 | | UINT8 m_cki_bus; /* CKI bus */ |
| 247 | | UINT8 m_p; /* adder p-input */ |
| 248 | | UINT8 m_n; /* adder n-input */ |
| 249 | | UINT8 m_adder_result; /* adder result */ |
| 250 | | UINT8 m_carry_in; /* carry in */ |
| 251 | | UINT8 m_status; |
| 252 | | UINT8 m_status_latch; |
| 253 | | UINT8 m_special_status; |
| 254 | | UINT8 m_call_latch; |
| 255 | | UINT8 m_add_latch; |
| 256 | | UINT8 m_branch_latch; |
| 257 | | int m_subcycle; |
| 258 | | UINT8 m_ram_address; |
| 259 | | UINT16 m_ram_data; |
| 260 | | UINT16 m_rom_address; |
| 261 | | UINT16 m_opcode; |
| 262 | | UINT32 m_decode; |
| 263 | | int m_icount; |
| 264 | | UINT16 m_o_mask; /* mask to determine the number of O outputs */ |
| 265 | | UINT16 m_r_mask; /* mask to determine the number of R outputs */ |
| 266 | | UINT8 m_pc_size; /* how bits in the PC register */ |
| 267 | | UINT8 m_byte_size; /* 8 or 9 bit bytes */ |
| 268 | | UINT8 m_x_bits; /* determine the number of bits in the X register */ |
| 269 | | const UINT32 *m_decode_table; |
| 270 | | const tms0980_config *config; |
| 271 | | address_space *m_program; |
| 272 | | address_space *m_data; |
| 273 | | |
| 274 | | devcb_resolved_read8 m_read_k; |
| 275 | | devcb_resolved_write16 m_write_o; |
| 276 | | devcb_resolved_write16 m_write_r; |
| 277 | | }; |
| 278 | | |
| 279 | | |
| 280 | 239 | static const UINT8 tms0980_c2_value[4] = |
| 281 | 240 | { |
| 282 | 241 | 0x00, 0x02, 0x01, 0x03 |
| r23640 | r23641 | |
| 454 | 413 | }; |
| 455 | 414 | |
| 456 | 415 | |
| 457 | | INLINE tms0980_state *get_safe_token(device_t *device) |
| 458 | | { |
| 459 | | assert(device != NULL); |
| 460 | | assert(device->type() == TMS0980 || |
| 461 | | device->type() == TMS1000 || |
| 462 | | device->type() == TMS1070 || |
| 463 | | device->type() == TMS1100 || |
| 464 | | device->type() == TMS1200 || |
| 465 | | device->type() == TMS1270 || |
| 466 | | device->type() == TMS1300 ); |
| 467 | | return (tms0980_state *)downcast<legacy_cpu_device *>(device)->token(); |
| 468 | | } |
| 469 | | |
| 470 | | |
| 471 | | static ADDRESS_MAP_START(tms0980_internal_rom, AS_PROGRAM, 16, legacy_cpu_device) |
| 416 | static ADDRESS_MAP_START(tms0980_internal_rom, AS_PROGRAM, 16, tms1xxx_cpu_device) |
| 472 | 417 | AM_RANGE( 0x0000, 0x0FFF ) AM_ROM |
| 473 | 418 | ADDRESS_MAP_END |
| 474 | 419 | |
| 475 | 420 | |
| 476 | | static ADDRESS_MAP_START(tms0980_internal_ram, AS_DATA, 8, legacy_cpu_device) |
| 421 | static ADDRESS_MAP_START(tms0980_internal_ram, AS_DATA, 8, tms1xxx_cpu_device) |
| 477 | 422 | AM_RANGE( 0x0000, 0x0FFF ) AM_RAM |
| 478 | 423 | ADDRESS_MAP_END |
| 479 | 424 | |
| 480 | 425 | |
| 481 | | static ADDRESS_MAP_START(program_10bit_8, AS_PROGRAM, 8, legacy_cpu_device) |
| 426 | static ADDRESS_MAP_START(program_10bit_8, AS_PROGRAM, 8, tms1xxx_cpu_device) |
| 482 | 427 | AM_RANGE( 0x000, 0x3ff ) AM_ROM |
| 483 | 428 | ADDRESS_MAP_END |
| 484 | 429 | |
| 485 | 430 | |
| 486 | | static ADDRESS_MAP_START(program_11bit_8, AS_PROGRAM, 8, legacy_cpu_device) |
| 431 | static ADDRESS_MAP_START(program_11bit_8, AS_PROGRAM, 8, tms1xxx_cpu_device) |
| 487 | 432 | AM_RANGE( 0x000, 0x7ff ) AM_ROM |
| 488 | 433 | ADDRESS_MAP_END |
| 489 | 434 | |
| 490 | 435 | |
| 491 | | static ADDRESS_MAP_START(data_6bit, AS_DATA, 8, legacy_cpu_device) |
| 436 | static ADDRESS_MAP_START(data_6bit, AS_DATA, 8, tms1xxx_cpu_device) |
| 492 | 437 | AM_RANGE( 0x00, 0x3f ) AM_RAM |
| 493 | 438 | ADDRESS_MAP_END |
| 494 | 439 | |
| 495 | 440 | |
| 496 | | static ADDRESS_MAP_START(data_7bit, AS_DATA, 8, legacy_cpu_device) |
| 441 | static ADDRESS_MAP_START(data_7bit, AS_DATA, 8, tms1xxx_cpu_device) |
| 497 | 442 | AM_RANGE( 0x00, 0x7f ) AM_RAM |
| 498 | 443 | ADDRESS_MAP_END |
| 499 | 444 | |
| 500 | 445 | |
| 501 | | static void cpu_init_tms_common( legacy_cpu_device *device, const UINT32* decode_table, UINT16 o_mask, UINT16 r_mask, UINT8 pc_size, UINT8 byte_size, UINT8 x_bits ) |
| 446 | void tms1xxx_cpu_device::device_start() |
| 502 | 447 | { |
| 503 | | tms0980_state *cpustate = get_safe_token( device ); |
| 448 | m_program = &space( AS_PROGRAM ); |
| 449 | m_data = &space( AS_DATA ); |
| 504 | 450 | |
| 505 | | cpustate->config = (const tms0980_config *) device->static_config(); |
| 451 | m_read_k.resolve_safe(0xff); |
| 452 | m_write_o.resolve_safe(); |
| 453 | m_write_r.resolve_safe(); |
| 506 | 454 | |
| 507 | | assert( cpustate->config != NULL ); |
| 455 | save_item( NAME(m_prev_pc) ); |
| 456 | save_item( NAME(m_prev_pa) ); |
| 457 | save_item( NAME(m_pc) ); |
| 458 | save_item( NAME(m_pa) ); |
| 459 | save_item( NAME(m_sr) ); |
| 460 | save_item( NAME(m_pb) ); |
| 461 | save_item( NAME(m_a) ); |
| 462 | save_item( NAME(m_x) ); |
| 463 | save_item( NAME(m_y) ); |
| 464 | save_item( NAME(m_dam) ); |
| 465 | save_item( NAME(m_ca) ); |
| 466 | save_item( NAME(m_cb) ); |
| 467 | save_item( NAME(m_cs) ); |
| 468 | save_item( NAME(m_r) ); |
| 469 | save_item( NAME(m_o) ); |
| 470 | save_item( NAME(m_cki_bus) ); |
| 471 | save_item( NAME(m_p) ); |
| 472 | save_item( NAME(m_n) ); |
| 473 | save_item( NAME(m_adder_result) ); |
| 474 | save_item( NAME(m_carry_in) ); |
| 475 | save_item( NAME(m_status) ); |
| 476 | save_item( NAME(m_status_latch) ); |
| 477 | save_item( NAME(m_special_status) ); |
| 478 | save_item( NAME(m_call_latch) ); |
| 479 | save_item( NAME(m_add_latch) ); |
| 480 | save_item( NAME(m_branch_latch) ); |
| 481 | save_item( NAME(m_subcycle) ); |
| 482 | save_item( NAME(m_ram_address) ); |
| 483 | save_item( NAME(m_ram_data) ); |
| 484 | save_item( NAME(m_rom_address) ); |
| 485 | save_item( NAME(m_opcode) ); |
| 486 | save_item( NAME(m_decode) ); |
| 508 | 487 | |
| 509 | | cpustate->m_decode_table = decode_table; |
| 510 | | cpustate->m_o_mask = o_mask; |
| 511 | | cpustate->m_r_mask = r_mask; |
| 512 | | cpustate->m_pc_size = pc_size; |
| 513 | | cpustate->m_byte_size = byte_size; |
| 514 | | cpustate->m_x_bits = x_bits; |
| 488 | // Register state for debugger |
| 489 | state_add( TMS0980_PC, "PC", m_pc ).callimport().callexport().formatstr("%02X"); |
| 490 | state_add( TMS0980_SR, "SR", m_sr ).callimport().callexport().formatstr("%01X"); |
| 491 | state_add( TMS0980_PA, "PA", m_pa ).callimport().callexport().formatstr("%01X"); |
| 492 | state_add( TMS0980_PB, "PB", m_pb ).callimport().callexport().formatstr("%01X"); |
| 493 | state_add( TMS0980_A, "A", m_a ).callimport().callexport().formatstr("%01X"); |
| 494 | state_add( TMS0980_X, "X", m_x ).callimport().callexport().formatstr("%01X"); |
| 495 | state_add( TMS0980_Y, "Y", m_y ).callimport().callexport().formatstr("%01X"); |
| 496 | state_add( TMS0980_STATUS, "STATUS", m_status ).callimport().callexport().formatstr("%01X"); |
| 515 | 497 | |
| 516 | | cpustate->m_program = &device->space( AS_PROGRAM ); |
| 517 | | cpustate->m_data = &device->space( AS_DATA ); |
| 498 | state_add(STATE_GENPC, "curpc", m_pc).callimport().callexport().formatstr("%8s").noshow(); |
| 499 | state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).callimport().callexport().formatstr("%8s").noshow(); |
| 518 | 500 | |
| 519 | | cpustate->m_read_k.resolve(cpustate->config->read_k, *device); |
| 520 | | cpustate->m_write_o.resolve(cpustate->config->write_o, *device); |
| 521 | | cpustate->m_write_r.resolve(cpustate->config->write_r, *device); |
| 522 | | |
| 523 | | |
| 524 | | device->save_item( NAME(cpustate->m_prev_pc) ); |
| 525 | | device->save_item( NAME(cpustate->m_prev_pa) ); |
| 526 | | device->save_item( NAME(cpustate->m_pc) ); |
| 527 | | device->save_item( NAME(cpustate->m_pa) ); |
| 528 | | device->save_item( NAME(cpustate->m_sr) ); |
| 529 | | device->save_item( NAME(cpustate->m_pb) ); |
| 530 | | device->save_item( NAME(cpustate->m_a) ); |
| 531 | | device->save_item( NAME(cpustate->m_x) ); |
| 532 | | device->save_item( NAME(cpustate->m_y) ); |
| 533 | | device->save_item( NAME(cpustate->m_dam) ); |
| 534 | | device->save_item( NAME(cpustate->m_ca) ); |
| 535 | | device->save_item( NAME(cpustate->m_cb) ); |
| 536 | | device->save_item( NAME(cpustate->m_cs) ); |
| 537 | | device->save_item( NAME(cpustate->m_r) ); |
| 538 | | device->save_item( NAME(cpustate->m_o) ); |
| 539 | | device->save_item( NAME(cpustate->m_cki_bus) ); |
| 540 | | device->save_item( NAME(cpustate->m_p) ); |
| 541 | | device->save_item( NAME(cpustate->m_n) ); |
| 542 | | device->save_item( NAME(cpustate->m_adder_result) ); |
| 543 | | device->save_item( NAME(cpustate->m_carry_in) ); |
| 544 | | device->save_item( NAME(cpustate->m_status) ); |
| 545 | | device->save_item( NAME(cpustate->m_status_latch) ); |
| 546 | | device->save_item( NAME(cpustate->m_special_status) ); |
| 547 | | device->save_item( NAME(cpustate->m_call_latch) ); |
| 548 | | device->save_item( NAME(cpustate->m_add_latch) ); |
| 549 | | device->save_item( NAME(cpustate->m_branch_latch) ); |
| 550 | | device->save_item( NAME(cpustate->m_subcycle) ); |
| 551 | | device->save_item( NAME(cpustate->m_ram_address) ); |
| 552 | | device->save_item( NAME(cpustate->m_ram_data) ); |
| 553 | | device->save_item( NAME(cpustate->m_rom_address) ); |
| 554 | | device->save_item( NAME(cpustate->m_opcode) ); |
| 555 | | device->save_item( NAME(cpustate->m_decode) ); |
| 501 | m_icountptr = &m_icount; |
| 556 | 502 | } |
| 557 | 503 | |
| 558 | 504 | |
| 559 | | static CPU_INIT( tms0980 ) |
| 505 | void tms1xxx_cpu_device::device_reset() |
| 560 | 506 | { |
| 561 | | cpu_init_tms_common( device, tms0980_decode, 0x00ff, 0x07ff, 7, 9, 4 ); |
| 507 | m_pa = 0x0F; |
| 508 | m_pb = 0x0F; |
| 509 | m_pc = 0; |
| 510 | m_dam = 0; |
| 511 | m_ca = 0; |
| 512 | m_cb = 0; |
| 513 | m_cs = 0; |
| 514 | m_subcycle = 0; |
| 515 | m_status = 1; |
| 516 | m_status_latch = 0; |
| 517 | m_call_latch = 0; |
| 518 | m_add_latch = 0; |
| 519 | m_branch_latch = 0; |
| 520 | m_r = 0; |
| 521 | m_o = 0; |
| 522 | m_ram_address = 0; |
| 523 | m_decode = F_ILL; |
| 524 | m_opcode = 0; |
| 562 | 525 | } |
| 563 | 526 | |
| 564 | 527 | |
| 565 | | static CPU_INIT( tms1000 ) |
| 566 | | { |
| 567 | | cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8, 2 ); |
| 568 | | } |
| 569 | | |
| 570 | | |
| 571 | | static CPU_INIT( tms1070 ) |
| 572 | | { |
| 573 | | cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8, 2 ); |
| 574 | | } |
| 575 | | |
| 576 | | |
| 577 | | static CPU_INIT( tms1200 ) |
| 578 | | { |
| 579 | | cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x1fff, 6, 8, 2 ); |
| 580 | | } |
| 581 | | |
| 582 | | |
| 583 | | static CPU_INIT( tms1270 ) |
| 584 | | { |
| 585 | | cpu_init_tms_common( device, tms1000_default_decode, 0x03ff, 0x1fff, 6, 8, 2 ); |
| 586 | | } |
| 587 | | |
| 588 | | |
| 589 | | static CPU_INIT( tms1100 ) |
| 590 | | { |
| 591 | | cpu_init_tms_common( device, tms1100_default_decode, 0x00ff, 0x07ff, 6, 8, 3 ); |
| 592 | | } |
| 593 | | |
| 594 | | |
| 595 | | static CPU_INIT( tms1300 ) |
| 596 | | { |
| 597 | | cpu_init_tms_common( device, tms1100_default_decode, 0x00ff, 0xffff, 6, 8, 3 ); |
| 598 | | } |
| 599 | | |
| 600 | | |
| 601 | | static CPU_RESET( tms0980 ) |
| 602 | | { |
| 603 | | tms0980_state *cpustate = get_safe_token( device ); |
| 604 | | |
| 605 | | cpustate->m_pa = 0x0F; |
| 606 | | cpustate->m_pb = 0x0F; |
| 607 | | cpustate->m_pc = 0; |
| 608 | | cpustate->m_dam = 0; |
| 609 | | cpustate->m_ca = 0; |
| 610 | | cpustate->m_cb = 0; |
| 611 | | cpustate->m_cs = 0; |
| 612 | | cpustate->m_subcycle = 0; |
| 613 | | cpustate->m_status = 1; |
| 614 | | cpustate->m_status_latch = 0; |
| 615 | | cpustate->m_call_latch = 0; |
| 616 | | cpustate->m_add_latch = 0; |
| 617 | | cpustate->m_branch_latch = 0; |
| 618 | | cpustate->m_r = 0; |
| 619 | | cpustate->m_o = 0; |
| 620 | | cpustate->m_ram_address = 0; |
| 621 | | cpustate->m_decode = F_ILL; |
| 622 | | cpustate->m_opcode = 0; |
| 623 | | } |
| 624 | | |
| 625 | | |
| 626 | 528 | /* |
| 627 | 529 | The program counter is implemented using PRNG logic and gets incremented as follows: |
| 628 | 530 | |
| r23640 | r23641 | |
| 743 | 645 | |
| 744 | 646 | tms0980_nect_pc below implements an indentical function to this in a somewhat more elegant way. |
| 745 | 647 | */ |
| 746 | | INLINE void tms0980_next_pc( tms0980_state *cpustate ) |
| 648 | void tms1xxx_cpu_device::next_pc() |
| 747 | 649 | { |
| 748 | | if ( cpustate->m_byte_size > 8 ) |
| 650 | if ( m_byte_size > 8 ) |
| 749 | 651 | { |
| 750 | | UINT8 xorval = ( cpustate->m_pc & 0x3F ) == 0x3F ? 1 : 0; |
| 751 | | UINT8 new_bit = ( ( cpustate->m_pc ^ ( cpustate->m_pc << 1 ) ) & 0x40 ) ? xorval : 1 - xorval; |
| 652 | UINT8 xorval = ( m_pc & 0x3F ) == 0x3F ? 1 : 0; |
| 653 | UINT8 new_bit = ( ( m_pc ^ ( m_pc << 1 ) ) & 0x40 ) ? xorval : 1 - xorval; |
| 752 | 654 | |
| 753 | | cpustate->m_pc = ( cpustate->m_pc << 1 ) | new_bit; |
| 655 | m_pc = ( m_pc << 1 ) | new_bit; |
| 754 | 656 | } |
| 755 | 657 | else |
| 756 | 658 | { |
| 757 | | cpustate->m_pc = tms1000_next_pc[ cpustate->m_pc & 0x3f ]; |
| 659 | m_pc = tms1000_next_pc[ m_pc & 0x3f ]; |
| 758 | 660 | } |
| 759 | 661 | } |
| 760 | 662 | |
| r23640 | r23641 | |
| 772 | 674 | }; |
| 773 | 675 | |
| 774 | 676 | |
| 775 | | static void tms0980_set_cki_bus( device_t *device ) |
| 677 | void tms1xxx_cpu_device::set_cki_bus() |
| 776 | 678 | { |
| 777 | | tms0980_state *cpustate = get_safe_token( device ); |
| 778 | | |
| 779 | | switch( cpustate->m_opcode & 0x1F8 ) |
| 679 | switch( m_opcode & 0x1F8 ) |
| 780 | 680 | { |
| 781 | 681 | case 0x008: |
| 782 | | if ( !cpustate->m_read_k.isnull() ) |
| 783 | | { |
| 784 | | cpustate->m_cki_bus = cpustate->m_read_k( 0, 0xff ); |
| 785 | | } |
| 786 | | else |
| 787 | | { |
| 788 | | cpustate->m_cki_bus = 0x0F; |
| 789 | | } |
| 682 | m_cki_bus = m_read_k( 0, 0xff ); |
| 790 | 683 | break; |
| 791 | 684 | case 0x020: case 0x028: |
| 792 | | cpustate->m_cki_bus = 0; |
| 685 | m_cki_bus = 0; |
| 793 | 686 | break; |
| 794 | 687 | case 0x030: case 0x038: |
| 795 | | cpustate->m_cki_bus = tms0980_nbit_value[ cpustate->m_opcode & 0x03 ]; |
| 688 | m_cki_bus = tms0980_nbit_value[ m_opcode & 0x03 ]; |
| 796 | 689 | break; |
| 797 | 690 | case 0x000: |
| 798 | 691 | case 0x040: case 0x048: |
| r23640 | r23641 | |
| 805 | 698 | case 0x0d0: case 0x0d8: |
| 806 | 699 | case 0x0e0: case 0x0e8: |
| 807 | 700 | case 0x0f0: case 0x0f8: |
| 808 | | cpustate->m_cki_bus = tms0980_c4_value[ cpustate->m_opcode & 0x0F ]; |
| 701 | m_cki_bus = tms0980_c4_value[ m_opcode & 0x0F ]; |
| 809 | 702 | break; |
| 810 | 703 | default: |
| 811 | | cpustate->m_cki_bus = 0x0F; |
| 704 | m_cki_bus = 0x0F; |
| 812 | 705 | break; |
| 813 | 706 | } |
| 814 | 707 | } |
| 815 | 708 | |
| 816 | 709 | |
| 817 | | static CPU_EXECUTE( tms0980 ) |
| 710 | void tms1xxx_cpu_device::execute_run() |
| 818 | 711 | { |
| 819 | | tms0980_state *cpustate = get_safe_token( device ); |
| 820 | | |
| 821 | 712 | do |
| 822 | 713 | { |
| 823 | | // debugger_instruction_hook( device, ( ( cpustate->m_pa << cpustate->m_pc_size ) | cpustate->m_pc ) << 1 ); |
| 824 | | cpustate->m_icount--; |
| 825 | | switch( cpustate->m_subcycle ) |
| 714 | // debugger_instruction_hook( this, ( ( m_pa << m_pc_size ) | m_pc ) << 1 ); |
| 715 | m_icount--; |
| 716 | switch( m_subcycle ) |
| 826 | 717 | { |
| 827 | 718 | case 0: |
| 828 | 719 | /* fetch: rom address 0 */ |
| 829 | 720 | /* execute: read ram, alu input, execute br/call, k input valid */ |
| 830 | | tms0980_set_cki_bus( device ); |
| 831 | | cpustate->m_ram_data = cpustate->m_data->read_byte( cpustate->m_ram_address ); |
| 832 | | cpustate->m_status = 1; |
| 833 | | cpustate->m_p = 0; |
| 834 | | cpustate->m_n = 0; |
| 835 | | cpustate->m_carry_in = 0; |
| 721 | set_cki_bus(); |
| 722 | m_ram_data = m_data->read_byte( m_ram_address ); |
| 723 | m_status = 1; |
| 724 | m_p = 0; |
| 725 | m_n = 0; |
| 726 | m_carry_in = 0; |
| 836 | 727 | break; |
| 837 | 728 | case 1: |
| 838 | 729 | /* fetch: rom address 1 */ |
| 839 | | cpustate->m_rom_address = ( cpustate->m_ca << ( cpustate->m_pc_size + 4 ) ) | ( cpustate->m_pa << cpustate->m_pc_size ) | cpustate->m_pc; |
| 730 | m_rom_address = ( m_ca << ( m_pc_size + 4 ) ) | ( m_pa << m_pc_size ) | m_pc; |
| 840 | 731 | /* execute: k input valid */ |
| 841 | | if ( cpustate->m_decode & MICRO_MASK ) |
| 732 | if ( m_decode & MICRO_MASK ) |
| 842 | 733 | { |
| 843 | 734 | /* Check N inputs */ |
| 844 | | if ( cpustate->m_decode & ( M_15TN | M_ATN | M_CKN | M_MTN | M_NATN ) ) |
| 735 | if ( m_decode & ( M_15TN | M_ATN | M_CKN | M_MTN | M_NATN ) ) |
| 845 | 736 | { |
| 846 | | cpustate->m_n = 0; |
| 847 | | if ( cpustate->m_decode & M_15TN ) |
| 737 | m_n = 0; |
| 738 | if ( m_decode & M_15TN ) |
| 848 | 739 | { |
| 849 | | cpustate->m_n |= 0x0F; |
| 740 | m_n |= 0x0F; |
| 850 | 741 | } |
| 851 | | if ( cpustate->m_decode & M_ATN ) |
| 742 | if ( m_decode & M_ATN ) |
| 852 | 743 | { |
| 853 | | cpustate->m_n |= cpustate->m_a; |
| 744 | m_n |= m_a; |
| 854 | 745 | } |
| 855 | | if ( cpustate->m_decode & M_CKN ) |
| 746 | if ( m_decode & M_CKN ) |
| 856 | 747 | { |
| 857 | | cpustate->m_n |= cpustate->m_cki_bus; |
| 748 | m_n |= m_cki_bus; |
| 858 | 749 | } |
| 859 | | if ( cpustate->m_decode & M_MTN ) |
| 750 | if ( m_decode & M_MTN ) |
| 860 | 751 | { |
| 861 | | cpustate->m_n |= cpustate->m_ram_data; |
| 752 | m_n |= m_ram_data; |
| 862 | 753 | } |
| 863 | | if ( cpustate->m_decode & M_NATN ) |
| 754 | if ( m_decode & M_NATN ) |
| 864 | 755 | { |
| 865 | | cpustate->m_n |= ( ( ~cpustate->m_a ) & 0x0F ); |
| 756 | m_n |= ( ( ~m_a ) & 0x0F ); |
| 866 | 757 | } |
| 867 | 758 | } |
| 868 | 759 | |
| 869 | 760 | |
| 870 | 761 | /* Check P inputs */ |
| 871 | | if ( cpustate->m_decode & ( M_CKP | M_DMTP | M_MTP | M_NDMTP | M_YTP ) ) |
| 762 | if ( m_decode & ( M_CKP | M_DMTP | M_MTP | M_NDMTP | M_YTP ) ) |
| 872 | 763 | { |
| 873 | | cpustate->m_p = 0; |
| 874 | | if ( cpustate->m_decode & M_CKP ) |
| 764 | m_p = 0; |
| 765 | if ( m_decode & M_CKP ) |
| 875 | 766 | { |
| 876 | | cpustate->m_p |= cpustate->m_cki_bus; |
| 767 | m_p |= m_cki_bus; |
| 877 | 768 | } |
| 878 | | if ( cpustate->m_decode & M_DMTP ) |
| 769 | if ( m_decode & M_DMTP ) |
| 879 | 770 | { |
| 880 | | cpustate->m_p |= cpustate->m_dam; |
| 771 | m_p |= m_dam; |
| 881 | 772 | } |
| 882 | | if ( cpustate->m_decode & M_MTP ) |
| 773 | if ( m_decode & M_MTP ) |
| 883 | 774 | { |
| 884 | | cpustate->m_p |= cpustate->m_ram_data; |
| 775 | m_p |= m_ram_data; |
| 885 | 776 | } |
| 886 | | if ( cpustate->m_decode & M_NDMTP ) |
| 777 | if ( m_decode & M_NDMTP ) |
| 887 | 778 | { |
| 888 | | cpustate->m_p |= ( ( ~cpustate->m_dam ) & 0x0F ); |
| 779 | m_p |= ( ( ~m_dam ) & 0x0F ); |
| 889 | 780 | } |
| 890 | | if ( cpustate->m_decode & M_YTP ) |
| 781 | if ( m_decode & M_YTP ) |
| 891 | 782 | { |
| 892 | | cpustate->m_p |= cpustate->m_y; |
| 783 | m_p |= m_y; |
| 893 | 784 | } |
| 894 | 785 | } |
| 895 | 786 | |
| 896 | 787 | /* Carry In input */ |
| 897 | | if ( cpustate->m_decode & M_CIN ) |
| 788 | if ( m_decode & M_CIN ) |
| 898 | 789 | { |
| 899 | | cpustate->m_carry_in = 1; |
| 790 | m_carry_in = 1; |
| 900 | 791 | } |
| 901 | 792 | } |
| 902 | 793 | break; |
| r23640 | r23641 | |
| 904 | 795 | /* fetch: nothing */ |
| 905 | 796 | /* execute: write ram */ |
| 906 | 797 | /* perform adder logic */ |
| 907 | | cpustate->m_adder_result = cpustate->m_p + cpustate->m_n + cpustate->m_carry_in; |
| 908 | | if ( cpustate->m_decode & MICRO_MASK ) |
| 798 | m_adder_result = m_p + m_n + m_carry_in; |
| 799 | if ( m_decode & MICRO_MASK ) |
| 909 | 800 | { |
| 910 | | if ( cpustate->m_decode & M_NE ) |
| 801 | if ( m_decode & M_NE ) |
| 911 | 802 | { |
| 912 | | if ( cpustate->m_n == cpustate->m_p ) |
| 803 | if ( m_n == m_p ) |
| 913 | 804 | { |
| 914 | | cpustate->m_status = 0; |
| 805 | m_status = 0; |
| 915 | 806 | } |
| 916 | 807 | } |
| 917 | | if ( cpustate->m_decode & M_C8 ) |
| 808 | if ( m_decode & M_C8 ) |
| 918 | 809 | { |
| 919 | | cpustate->m_status = cpustate->m_adder_result >> 4; |
| 810 | m_status = m_adder_result >> 4; |
| 920 | 811 | } |
| 921 | | if ( cpustate->m_decode & M_STO ) |
| 812 | if ( m_decode & M_STO ) |
| 922 | 813 | { |
| 923 | | //printf("write ram %02x data %01x\n", cpustate->m_ram_address, cpustate->m_a ); |
| 924 | | cpustate->m_data->write_byte( cpustate->m_ram_address, cpustate->m_a ); |
| 814 | //printf("write ram %02x data %01x\n", m_ram_address, m_a ); |
| 815 | m_data->write_byte( m_ram_address, m_a ); |
| 925 | 816 | } |
| 926 | | if ( cpustate->m_decode & M_CKM ) |
| 817 | if ( m_decode & M_CKM ) |
| 927 | 818 | { |
| 928 | | //printf("write ram %02x data %01x\n", cpustate->m_ram_address, cpustate->m_cki_bus ); |
| 929 | | cpustate->m_data->write_byte( cpustate->m_ram_address, cpustate->m_cki_bus ); |
| 819 | //printf("write ram %02x data %01x\n", m_ram_address, m_cki_bus ); |
| 820 | m_data->write_byte( m_ram_address, m_cki_bus ); |
| 930 | 821 | } |
| 931 | 822 | } |
| 932 | 823 | else |
| 933 | 824 | { |
| 934 | | if ( cpustate->m_decode & F_SBIT ) |
| 825 | if ( m_decode & F_SBIT ) |
| 935 | 826 | { |
| 936 | | //printf("write ram %02x data %01x\n", cpustate->m_ram_address, cpustate->m_ram_data | tms0980_bit_value[ cpustate->m_opcode & 0x03 ] ); |
| 937 | | cpustate->m_data->write_byte( cpustate->m_ram_address, cpustate->m_ram_data | tms0980_bit_value[ cpustate->m_opcode & 0x03 ] ); |
| 827 | //printf("write ram %02x data %01x\n", m_ram_address, m_ram_data | tms0980_bit_value[ m_opcode & 0x03 ] ); |
| 828 | m_data->write_byte( m_ram_address, m_ram_data | tms0980_bit_value[ m_opcode & 0x03 ] ); |
| 938 | 829 | } |
| 939 | | if ( cpustate->m_decode & F_RBIT ) |
| 830 | if ( m_decode & F_RBIT ) |
| 940 | 831 | { |
| 941 | | //printf("write ram %02x data %01x\n", cpustate->m_ram_address, cpustate->m_ram_data & tms0980_nbit_value[ cpustate->m_opcode & 0x03 ] ); |
| 942 | | cpustate->m_data->write_byte( cpustate->m_ram_address, cpustate->m_ram_data & tms0980_nbit_value[ cpustate->m_opcode & 0x03 ] ); |
| 832 | //printf("write ram %02x data %01x\n", m_ram_address, m_ram_data & tms0980_nbit_value[ m_opcode & 0x03 ] ); |
| 833 | m_data->write_byte( m_ram_address, m_ram_data & tms0980_nbit_value[ m_opcode & 0x03 ] ); |
| 943 | 834 | } |
| 944 | | if ( cpustate->m_decode & F_SETR ) |
| 835 | if ( m_decode & F_SETR ) |
| 945 | 836 | { |
| 946 | | cpustate->m_r = cpustate->m_r | ( 1 << cpustate->m_y ); |
| 947 | | if ( !cpustate->m_write_r.isnull() ) |
| 948 | | { |
| 949 | | cpustate->m_write_r( 0, cpustate->m_r & cpustate->m_r_mask, 0xffff ); |
| 950 | | } |
| 837 | m_r = m_r | ( 1 << m_y ); |
| 838 | m_write_r( 0, m_r & m_r_mask, 0xffff ); |
| 951 | 839 | } |
| 952 | | if ( cpustate->m_decode & F_RSTR ) |
| 840 | if ( m_decode & F_RSTR ) |
| 953 | 841 | { |
| 954 | | cpustate->m_r = cpustate->m_r & ( ~( 1 << cpustate->m_y ) ); |
| 955 | | if ( !cpustate->m_write_r.isnull() ) |
| 956 | | { |
| 957 | | cpustate->m_write_r( 0, cpustate->m_r & cpustate->m_r_mask, 0xffff ); |
| 958 | | } |
| 842 | m_r = m_r & ( ~( 1 << m_y ) ); |
| 843 | m_write_r( 0, m_r & m_r_mask, 0xffff ); |
| 959 | 844 | } |
| 960 | | if ( cpustate->m_decode & F_TDO ) |
| 845 | if ( m_decode & F_TDO ) |
| 961 | 846 | { |
| 962 | 847 | /* Calculate O-outputs based on status latch, A, and the output PLA configuration */ |
| 963 | | cpustate->m_o = cpustate->config->o_pla[ ( cpustate->m_status_latch << 4 ) | cpustate->m_a ]; |
| 964 | | if ( ( cpustate->config->o_pla[ ( cpustate->m_status_latch << 4 ) | cpustate->m_a ] & 0xFF00 ) == 0xFF00 ) |
| 848 | m_o = c_output_pla[ ( m_status_latch << 4 ) | m_a ]; |
| 849 | if ( ( c_output_pla[ ( m_status_latch << 4 ) | m_a ] & 0xFF00 ) == 0xFF00 ) |
| 965 | 850 | { |
| 966 | | logerror("unknown output pla mapping for status latch = %d and a = %X\n", cpustate->m_status_latch, cpustate->m_a); |
| 851 | logerror("unknown output pla mapping for status latch = %d and a = %X\n", m_status_latch, m_a); |
| 967 | 852 | } |
| 968 | | //if ( ( cpustate->config->o_pla[ ( cpustate->m_status_latch << 4 ) | cpustate->m_a ] & 0xFF00 ) == 0xFF00 ) |
| 969 | | //printf("****** o output m_status_latch = %X, m_a = %X\n", cpustate->m_status_latch, cpustate->m_a); |
| 853 | //if ( ( c_output_pla[ ( m_status_latch << 4 ) | m_a ] & 0xFF00 ) == 0xFF00 ) |
| 854 | //printf("****** o output m_status_latch = %X, m_a = %X\n", m_status_latch, m_a); |
| 970 | 855 | //else |
| 971 | | //printf("o output m_status_latch = %X, m_a = %X\n", cpustate->m_status_latch, cpustate->m_a); |
| 856 | //printf("o output m_status_latch = %X, m_a = %X\n", m_status_latch, m_a); |
| 972 | 857 | |
| 973 | | if ( !cpustate->m_write_o.isnull() ) |
| 974 | | { |
| 975 | | cpustate->m_write_o( 0, cpustate->m_o & cpustate->m_o_mask, 0xffff ); |
| 976 | | } |
| 858 | m_write_o( 0, m_o & m_o_mask, 0xffff ); |
| 977 | 859 | } |
| 978 | | if ( cpustate->m_decode & F_CLO ) |
| 860 | if ( m_decode & F_CLO ) |
| 979 | 861 | { |
| 980 | | cpustate->m_o = 0; |
| 981 | | if ( !cpustate->m_write_o.isnull() ) |
| 982 | | { |
| 983 | | cpustate->m_write_o( 0, cpustate->m_o & cpustate->m_o_mask, 0xffff ); |
| 984 | | } |
| 862 | m_o = 0; |
| 863 | m_write_o( 0, m_o & m_o_mask, 0xffff ); |
| 985 | 864 | } |
| 986 | | if ( cpustate->m_decode & F_LDX ) |
| 865 | if ( m_decode & F_LDX ) |
| 987 | 866 | { |
| 988 | | switch( cpustate->m_x_bits ) |
| 867 | switch( m_x_bits ) |
| 989 | 868 | { |
| 990 | 869 | case 2: |
| 991 | | cpustate->m_x = tms0980_c2_value[ cpustate->m_opcode & 0x03 ]; |
| 870 | m_x = tms0980_c2_value[ m_opcode & 0x03 ]; |
| 992 | 871 | break; |
| 993 | 872 | case 3: |
| 994 | | cpustate->m_x = tms0980_c3_value[ cpustate->m_opcode & 0x07 ]; |
| 873 | m_x = tms0980_c3_value[ m_opcode & 0x07 ]; |
| 995 | 874 | break; |
| 996 | 875 | case 4: |
| 997 | | cpustate->m_x = tms0980_c4_value[ cpustate->m_opcode & 0x0f ]; |
| 876 | m_x = tms0980_c4_value[ m_opcode & 0x0f ]; |
| 998 | 877 | break; |
| 999 | 878 | } |
| 1000 | 879 | } |
| 1001 | | if ( cpustate->m_decode & F_COMX ) |
| 880 | if ( m_decode & F_COMX ) |
| 1002 | 881 | { |
| 1003 | | switch ( cpustate->m_x_bits ) |
| 882 | switch ( m_x_bits ) |
| 1004 | 883 | { |
| 1005 | 884 | case 2: |
| 1006 | | cpustate->m_x = cpustate->m_x ^ 0x03; |
| 885 | m_x = m_x ^ 0x03; |
| 1007 | 886 | break; |
| 1008 | 887 | case 3: |
| 1009 | | cpustate->m_x = cpustate->m_x ^ 0x07; |
| 888 | m_x = m_x ^ 0x07; |
| 1010 | 889 | break; |
| 1011 | 890 | case 4: |
| 1012 | | cpustate->m_x = cpustate->m_x ^ 0x0f; |
| 891 | m_x = m_x ^ 0x0f; |
| 1013 | 892 | break; |
| 1014 | 893 | } |
| 1015 | 894 | } |
| 1016 | | if ( cpustate->m_decode & F_COMC ) |
| 895 | if ( m_decode & F_COMC ) |
| 1017 | 896 | { |
| 1018 | | cpustate->m_cb = cpustate->m_cb ^ 0x01; |
| 897 | m_cb = m_cb ^ 0x01; |
| 1019 | 898 | } |
| 1020 | | if ( cpustate->m_decode & F_LDP ) |
| 899 | if ( m_decode & F_LDP ) |
| 1021 | 900 | { |
| 1022 | | cpustate->m_pb = tms0980_c4_value[ cpustate->m_opcode & 0x0F ]; |
| 901 | m_pb = tms0980_c4_value[ m_opcode & 0x0F ]; |
| 1023 | 902 | } |
| 1024 | | if ( cpustate->m_decode & F_REAC ) |
| 903 | if ( m_decode & F_REAC ) |
| 1025 | 904 | { |
| 1026 | | cpustate->m_special_status = 0; |
| 905 | m_special_status = 0; |
| 1027 | 906 | } |
| 1028 | | if ( cpustate->m_decode & F_SEAC ) |
| 907 | if ( m_decode & F_SEAC ) |
| 1029 | 908 | { |
| 1030 | | cpustate->m_special_status = 1; |
| 909 | m_special_status = 1; |
| 1031 | 910 | } |
| 1032 | | if ( cpustate->m_decode == F_SAL ) |
| 911 | if ( m_decode == F_SAL ) |
| 1033 | 912 | { |
| 1034 | | cpustate->m_add_latch = 1; |
| 913 | m_add_latch = 1; |
| 1035 | 914 | } |
| 1036 | | if ( cpustate->m_decode == F_SBL ) |
| 915 | if ( m_decode == F_SBL ) |
| 1037 | 916 | { |
| 1038 | | cpustate->m_branch_latch = 1; |
| 917 | m_branch_latch = 1; |
| 1039 | 918 | } |
| 1040 | 919 | } |
| 1041 | 920 | break; |
| r23640 | r23641 | |
| 1045 | 924 | break; |
| 1046 | 925 | case 4: |
| 1047 | 926 | /* execute: register store */ |
| 1048 | | if ( cpustate->m_decode & MICRO_MASK ) |
| 927 | if ( m_decode & MICRO_MASK ) |
| 1049 | 928 | { |
| 1050 | | if ( cpustate->m_decode & M_AUTA ) |
| 929 | if ( m_decode & M_AUTA ) |
| 1051 | 930 | { |
| 1052 | | cpustate->m_a = cpustate->m_adder_result & 0x0F; |
| 931 | m_a = m_adder_result & 0x0F; |
| 1053 | 932 | } |
| 1054 | | if ( cpustate->m_decode & M_AUTY ) |
| 933 | if ( m_decode & M_AUTY ) |
| 1055 | 934 | { |
| 1056 | | cpustate->m_y = cpustate->m_adder_result & 0x0F; |
| 935 | m_y = m_adder_result & 0x0F; |
| 1057 | 936 | } |
| 1058 | | if ( cpustate->m_decode & M_STSL ) |
| 937 | if ( m_decode & M_STSL ) |
| 1059 | 938 | { |
| 1060 | | cpustate->m_status_latch = cpustate->m_status; |
| 939 | m_status_latch = m_status; |
| 1061 | 940 | } |
| 1062 | 941 | } |
| 1063 | 942 | /* fetch: fetch, update pc, ram address */ |
| 1064 | | if ( cpustate->m_byte_size > 8 ) |
| 943 | if ( m_byte_size > 8 ) |
| 1065 | 944 | { |
| 1066 | | debugger_instruction_hook( device, cpustate->m_rom_address << 1 ); |
| 1067 | | cpustate->m_opcode = cpustate->m_program->read_word( cpustate->m_rom_address << 1 ) & 0x1FF; |
| 945 | debugger_instruction_hook( this, m_rom_address << 1 ); |
| 946 | m_opcode = m_program->read_word( m_rom_address << 1 ) & 0x1FF; |
| 1068 | 947 | } |
| 1069 | 948 | else |
| 1070 | 949 | { |
| 1071 | | debugger_instruction_hook( device, cpustate->m_rom_address ); |
| 1072 | | cpustate->m_opcode = cpustate->m_program->read_byte( cpustate->m_rom_address ); |
| 950 | debugger_instruction_hook( this, m_rom_address ); |
| 951 | m_opcode = m_program->read_byte( m_rom_address ); |
| 1073 | 952 | } |
| 1074 | | tms0980_next_pc( cpustate ); |
| 953 | next_pc(); |
| 1075 | 954 | if (LOG) |
| 1076 | | logerror( "tms0980: read opcode %04x from %04x. Set pc to %04x\n", cpustate->m_opcode, cpustate->m_rom_address, cpustate->m_pc ); |
| 955 | logerror( "tms0980: read opcode %04x from %04x. Set pc to %04x\n", m_opcode, m_rom_address, m_pc ); |
| 1077 | 956 | |
| 1078 | 957 | /* ram address */ |
| 1079 | | cpustate->m_ram_address = ( cpustate->m_x << 4 ) | cpustate->m_y; |
| 958 | m_ram_address = ( m_x << 4 ) | m_y; |
| 1080 | 959 | break; |
| 1081 | 960 | case 5: |
| 1082 | 961 | /* fetch: instruction decode */ |
| 1083 | | cpustate->m_decode = cpustate->m_decode_table[ cpustate->m_opcode ]; |
| 962 | m_decode = m_decode_table[ m_opcode ]; |
| 1084 | 963 | /* execute: execute br/call */ |
| 1085 | | if ( cpustate->m_status ) |
| 964 | if ( m_status ) |
| 1086 | 965 | { |
| 1087 | | if ( cpustate->m_decode == F_BR ) |
| 966 | if ( m_decode == F_BR ) |
| 1088 | 967 | { |
| 1089 | | cpustate->m_ca = cpustate->m_cb; |
| 1090 | | if ( cpustate->m_call_latch == 0 ) |
| 968 | m_ca = m_cb; |
| 969 | if ( m_call_latch == 0 ) |
| 1091 | 970 | { |
| 1092 | | cpustate->m_pa = cpustate->m_pb; |
| 971 | m_pa = m_pb; |
| 1093 | 972 | } |
| 1094 | | cpustate->m_pc = cpustate->m_opcode & ( ( 1 << cpustate->m_pc_size ) - 1 ); |
| 973 | m_pc = m_opcode & ( ( 1 << m_pc_size ) - 1 ); |
| 1095 | 974 | } |
| 1096 | | if ( cpustate->m_decode == F_CALL ) |
| 975 | if ( m_decode == F_CALL ) |
| 1097 | 976 | { |
| 1098 | | UINT8 t = cpustate->m_pa; |
| 1099 | | if ( cpustate->m_call_latch == 0 ) |
| 977 | UINT8 t = m_pa; |
| 978 | if ( m_call_latch == 0 ) |
| 1100 | 979 | { |
| 1101 | | cpustate->m_sr = cpustate->m_pc; |
| 1102 | | cpustate->m_call_latch = 1; |
| 1103 | | cpustate->m_pa = cpustate->m_pb; |
| 1104 | | cpustate->m_cs = cpustate->m_ca; |
| 980 | m_sr = m_pc; |
| 981 | m_call_latch = 1; |
| 982 | m_pa = m_pb; |
| 983 | m_cs = m_ca; |
| 1105 | 984 | } |
| 1106 | | cpustate->m_ca = cpustate->m_cb; |
| 1107 | | cpustate->m_pb = t; |
| 1108 | | cpustate->m_pc = cpustate->m_opcode & ( ( 1 << cpustate->m_pc_size ) - 1 ); |
| 985 | m_ca = m_cb; |
| 986 | m_pb = t; |
| 987 | m_pc = m_opcode & ( ( 1 << m_pc_size ) - 1 ); |
| 1109 | 988 | } |
| 1110 | 989 | } |
| 1111 | | if ( cpustate->m_decode == F_RETN ) |
| 990 | if ( m_decode == F_RETN ) |
| 1112 | 991 | { |
| 1113 | | if ( cpustate->m_call_latch == 1 ) |
| 992 | if ( m_call_latch == 1 ) |
| 1114 | 993 | { |
| 1115 | | cpustate->m_pc = cpustate->m_sr; |
| 1116 | | cpustate->m_call_latch = 0; |
| 1117 | | cpustate->m_ca = cpustate->m_cs; |
| 994 | m_pc = m_sr; |
| 995 | m_call_latch = 0; |
| 996 | m_ca = m_cs; |
| 1118 | 997 | } |
| 1119 | | cpustate->m_add_latch = 0; |
| 1120 | | cpustate->m_pa = cpustate->m_pb; |
| 998 | m_add_latch = 0; |
| 999 | m_pa = m_pb; |
| 1121 | 1000 | } else { |
| 1122 | | cpustate->m_branch_latch = 0; |
| 1001 | m_branch_latch = 0; |
| 1123 | 1002 | } |
| 1124 | 1003 | break; |
| 1125 | 1004 | } |
| 1126 | | cpustate->m_subcycle = ( cpustate->m_subcycle + 1 ) % 6; |
| 1127 | | } while( cpustate->m_icount > 0 ); |
| 1005 | m_subcycle = ( m_subcycle + 1 ) % 6; |
| 1006 | } while( m_icount > 0 ); |
| 1128 | 1007 | } |
| 1129 | 1008 | |
| 1130 | 1009 | |
| 1131 | | static CPU_SET_INFO( tms0980 ) |
| 1010 | void tms0980_cpu_device::state_string_export(const device_state_entry &entry, astring &string) |
| 1132 | 1011 | { |
| 1133 | | tms0980_state *cpustate = get_safe_token( device ); |
| 1134 | | |
| 1135 | | switch( state ) |
| 1012 | switch( entry.index() ) |
| 1136 | 1013 | { |
| 1137 | | case CPUINFO_INT_PC: cpustate->m_pc = ( info->i >> 1 ) & 0x7f; cpustate->m_pa = ( info->i >> 8 ) & 0x0F; cpustate->m_cb = ( info->i >> 12 ) & 0x01; break; |
| 1138 | | case CPUINFO_INT_REGISTER + TMS0980_PC: cpustate->m_pc = info->i; break; |
| 1139 | | case CPUINFO_INT_REGISTER + TMS0980_SR: cpustate->m_sr = info->i; break; |
| 1140 | | case CPUINFO_INT_REGISTER + TMS0980_PA: cpustate->m_pa = info->i; break; |
| 1141 | | case CPUINFO_INT_REGISTER + TMS0980_PB: cpustate->m_pb = info->i; break; |
| 1142 | | case CPUINFO_INT_REGISTER + TMS0980_A: cpustate->m_a = info->i; break; |
| 1143 | | case CPUINFO_INT_REGISTER + TMS0980_X: cpustate->m_x = info->i; break; |
| 1144 | | case CPUINFO_INT_REGISTER + TMS0980_Y: cpustate->m_y = info->i; break; |
| 1145 | | case CPUINFO_INT_REGISTER + TMS0980_STATUS: cpustate->m_status = info->i; break; |
| 1014 | case STATE_GENPC: |
| 1015 | string.printf( "%03X", ( ( m_pa << 7 ) | m_pc ) << 1 ); |
| 1016 | break; |
| 1146 | 1017 | } |
| 1147 | 1018 | } |
| 1148 | 1019 | |
| 1149 | 1020 | |
| 1150 | | static CPU_GET_INFO( tms_generic ) |
| 1021 | void tms1000_cpu_device::state_string_export(const device_state_entry &entry, astring &string) |
| 1151 | 1022 | { |
| 1152 | | tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 1153 | | |
| 1154 | | switch(state) |
| 1023 | switch( entry.index() ) |
| 1155 | 1024 | { |
| 1156 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tms0980_state); break; |
| 1157 | | case CPUINFO_INT_INPUT_LINES: info->i = 1; break; |
| 1158 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; |
| 1159 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 1160 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 1161 | | case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; |
| 1162 | | case CPUINFO_INT_MAX_CYCLES: info->i = 6; break; |
| 1025 | case STATE_GENPC: |
| 1026 | string.printf( "%03X", ( m_pa << 6 ) | tms1000_pc_decode[ m_pc ] ); |
| 1027 | break; |
| 1028 | } |
| 1029 | } |
| 1163 | 1030 | |
| 1164 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; |
| 1165 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8 /* 4 */; break; |
| 1166 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 1167 | 1031 | |
| 1168 | | case CPUINFO_INT_PREVIOUSPC: info->i = ( ( cpustate->m_prev_pa << 7 ) | cpustate->m_prev_pc ) << 1; break; |
| 1169 | | case CPUINFO_INT_PC: info->i = ( ( cpustate->m_pa << 7 ) | cpustate->m_pc ) << 1; break; |
| 1170 | | case CPUINFO_INT_SP: info->i = 0xFFFF; break; |
| 1171 | | case CPUINFO_INT_REGISTER + TMS0980_PC: info->i = cpustate->m_pc; break; |
| 1172 | | case CPUINFO_INT_REGISTER + TMS0980_SR: info->i = cpustate->m_sr; break; |
| 1173 | | case CPUINFO_INT_REGISTER + TMS0980_PA: info->i = cpustate->m_pa; break; |
| 1174 | | case CPUINFO_INT_REGISTER + TMS0980_PB: info->i = cpustate->m_pb; break; |
| 1175 | | case CPUINFO_INT_REGISTER + TMS0980_A: info->i = cpustate->m_a; break; |
| 1176 | | case CPUINFO_INT_REGISTER + TMS0980_X: info->i = cpustate->m_x; break; |
| 1177 | | case CPUINFO_INT_REGISTER + TMS0980_Y: info->i = cpustate->m_y; break; |
| 1178 | | case CPUINFO_INT_REGISTER + TMS0980_STATUS: info->i = cpustate->m_status; break; |
| 1032 | void tms1100_cpu_device::state_string_export(const device_state_entry &entry, astring &string) |
| 1033 | { |
| 1034 | switch( entry.index() ) |
| 1035 | { |
| 1036 | case STATE_GENPC: |
| 1037 | string.printf( "%03X", ( m_ca << 10 ) | ( m_pa << 6 ) | m_pc ); |
| 1038 | break; |
| 1039 | } |
| 1040 | } |
| 1179 | 1041 | |
| 1180 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME( tms0980 ); break; |
| 1181 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms0980 ); break; |
| 1182 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME( tms0980 ); break; |
| 1183 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME( tms0980 ); break; |
| 1184 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->m_icount; break; |
| 1185 | 1042 | |
| 1186 | | case CPUINFO_STR_FAMILY: strcpy( info->s, "Texas Instruments TMS0980/TMS1000" ); break; |
| 1187 | | case CPUINFO_STR_VERSION: strcpy( info->s, "0.2" ); break; |
| 1188 | | case CPUINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break; |
| 1189 | | case CPUINFO_STR_CREDITS: strcpy( info->s, "Copyright the MESS and MAME teams" ); break; |
| 1043 | tms0980_cpu_device::tms0980_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1044 | : tms1xxx_cpu_device( mconfig, TMS0980, "TMS0980", tag, owner, clock, tms0980_decode, 0x00ff, 0x07ff, 7, 9, 4 |
| 1045 | , 12, ADDRESS_MAP_NAME( tms0980_internal_rom ), 7, ADDRESS_MAP_NAME( tms0980_internal_ram ) ) |
| 1046 | { |
| 1047 | } |
| 1190 | 1048 | |
| 1191 | | case CPUINFO_STR_FLAGS: strcpy( info->s, "N/A" ); break; |
| 1192 | 1049 | |
| 1193 | | case CPUINFO_STR_REGISTER + TMS0980_PC: sprintf( info->s, "PC:%02X", cpustate->m_pc ); break; |
| 1194 | | case CPUINFO_STR_REGISTER + TMS0980_SR: sprintf( info->s, "SR:%01X", cpustate->m_sr ); break; |
| 1195 | | case CPUINFO_STR_REGISTER + TMS0980_PA: sprintf( info->s, "PA:%01X", cpustate->m_pa ); break; |
| 1196 | | case CPUINFO_STR_REGISTER + TMS0980_PB: sprintf( info->s, "PB:%01X", cpustate->m_pb ); break; |
| 1197 | | case CPUINFO_STR_REGISTER + TMS0980_A: sprintf( info->s, "A:%01X", cpustate->m_a ); break; |
| 1198 | | case CPUINFO_STR_REGISTER + TMS0980_X: sprintf( info->s, "X:%01X", cpustate->m_x ); break; |
| 1199 | | case CPUINFO_STR_REGISTER + TMS0980_Y: sprintf( info->s, "Y:%01X", cpustate->m_y ); break; |
| 1200 | | case CPUINFO_STR_REGISTER + TMS0980_STATUS: sprintf( info->s, "STATUS:%01X", cpustate->m_status ); break; |
| 1201 | | |
| 1202 | | } |
| 1050 | offs_t tms0980_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 1051 | { |
| 1052 | extern CPU_DISASSEMBLE( tms0980 ); |
| 1053 | return CPU_DISASSEMBLE_NAME(tms0980)(this, buffer, pc, oprom, opram, options); |
| 1203 | 1054 | } |
| 1204 | 1055 | |
| 1205 | 1056 | |
| 1206 | | CPU_GET_INFO( tms0980 ) |
| 1057 | tms1000_cpu_device::tms1000_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1058 | : tms1xxx_cpu_device( mconfig, TMS1000, "TMS1000", tag, owner, clock, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8, 2 |
| 1059 | , 11, ADDRESS_MAP_NAME( program_11bit_8 ), 7, ADDRESS_MAP_NAME( data_7bit ) ) |
| 1207 | 1060 | { |
| 1208 | | tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 1209 | | |
| 1210 | | switch(state) |
| 1211 | | { |
| 1212 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; |
| 1213 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break; |
| 1214 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16 /* 9 */; break; |
| 1215 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break; |
| 1216 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break; |
| 1217 | | case CPUINFO_INT_PREVIOUSPC: info->i = ( ( cpustate->m_prev_pa << 7 ) | cpustate->m_prev_pc ) << 1; break; |
| 1218 | | case CPUINFO_INT_PC: info->i = ( ( cpustate->m_pa << 7 ) | cpustate->m_pc ) << 1; break; |
| 1219 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME( tms0980_internal_rom ); break; |
| 1220 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( tms0980_internal_ram ); break; |
| 1221 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms0980 ); break; |
| 1222 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms0980 ); break; |
| 1223 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS0980" ); break; |
| 1224 | | default: CPU_GET_INFO_CALL( tms_generic ); |
| 1225 | | } |
| 1226 | 1061 | } |
| 1227 | 1062 | |
| 1228 | 1063 | |
| 1229 | | CPU_GET_INFO( tms1000 ) |
| 1064 | tms1000_cpu_device::tms1000_cpu_device(const machine_config &mconfig, device_type type, const char*name, const char *tag, device_t *owner, UINT32 clock, UINT16 o_mask, UINT16 r_mask) |
| 1065 | : tms1xxx_cpu_device( mconfig, type, name, tag, owner, clock, tms1000_default_decode, o_mask, r_mask, 6, 8, 2 |
| 1066 | , 10, ADDRESS_MAP_NAME( program_10bit_8 ), 6, ADDRESS_MAP_NAME( data_6bit ) ) |
| 1230 | 1067 | { |
| 1231 | | tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 1232 | | |
| 1233 | | switch(state) |
| 1234 | | { |
| 1235 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; |
| 1236 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 1; break; |
| 1237 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; |
| 1238 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break; |
| 1239 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break; |
| 1240 | | case CPUINFO_INT_PREVIOUSPC: info->i = ( cpustate->m_prev_pa << 6 ) | tms1000_pc_decode[ cpustate->m_prev_pc ]; break; |
| 1241 | | case CPUINFO_INT_PC: info->i = ( cpustate->m_pa << 6 ) | tms1000_pc_decode[ cpustate->m_pc ]; break; |
| 1242 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME( program_10bit_8 ); break; |
| 1243 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( data_6bit ); break; |
| 1244 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1000 ); break; |
| 1245 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms1000 ); break; |
| 1246 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS1000" ); break; |
| 1247 | | default: CPU_GET_INFO_CALL( tms_generic ); |
| 1248 | | } |
| 1249 | 1068 | } |
| 1250 | 1069 | |
| 1251 | 1070 | |
| 1252 | | CPU_GET_INFO( tms1070 ) |
| 1071 | offs_t tms1000_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 1253 | 1072 | { |
| 1254 | | switch(state) |
| 1255 | | { |
| 1256 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1070 ); break; |
| 1257 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS1070" ); break; |
| 1258 | | default: CPU_GET_INFO_CALL( tms1000 ); |
| 1259 | | } |
| 1073 | extern CPU_DISASSEMBLE( tms1000 ); |
| 1074 | return CPU_DISASSEMBLE_NAME(tms1000)(this, buffer, pc, oprom, opram, options); |
| 1260 | 1075 | } |
| 1261 | 1076 | |
| 1262 | 1077 | |
| 1263 | | CPU_GET_INFO( tms1200 ) |
| 1078 | tms1070_cpu_device::tms1070_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1079 | : tms1000_cpu_device( mconfig, TMS1070, "TMS1070", tag, owner, clock, 0x00ff, 0x07ff ) |
| 1264 | 1080 | { |
| 1265 | | switch(state) |
| 1266 | | { |
| 1267 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1200 ); break; |
| 1268 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS1200" ); break; |
| 1269 | | default: CPU_GET_INFO_CALL( tms1000 ); |
| 1270 | | } |
| 1271 | 1081 | } |
| 1272 | 1082 | |
| 1273 | 1083 | |
| 1274 | | CPU_GET_INFO( tms1270 ) |
| 1084 | tms1200_cpu_device::tms1200_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1085 | : tms1000_cpu_device( mconfig, TMS1200, "TMS1200", tag, owner, clock, 0x00ff, 0x1fff ) |
| 1275 | 1086 | { |
| 1276 | | switch(state) |
| 1277 | | { |
| 1278 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1270 ); break; |
| 1279 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS1270" ); break; |
| 1280 | | default: CPU_GET_INFO_CALL( tms1000 ); |
| 1281 | | } |
| 1282 | 1087 | } |
| 1283 | 1088 | |
| 1284 | 1089 | |
| 1090 | tms1270_cpu_device::tms1270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1091 | : tms1000_cpu_device( mconfig, TMS1270, "TMS1270", tag, owner, clock, 0x03ff, 0x1fff ) |
| 1092 | { |
| 1093 | } |
| 1285 | 1094 | |
| 1286 | | CPU_GET_INFO( tms1100 ) |
| 1095 | |
| 1096 | tms1100_cpu_device::tms1100_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1097 | : tms1xxx_cpu_device( mconfig, TMS1100, "TMS1100", tag, owner, clock, tms1100_default_decode, 0x00ff, 0x07ff, 6, 8, 3 |
| 1098 | , 11, ADDRESS_MAP_NAME( program_11bit_8 ), 7, ADDRESS_MAP_NAME( data_7bit ) ) |
| 1287 | 1099 | { |
| 1288 | | tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 1100 | } |
| 1289 | 1101 | |
| 1290 | | switch(state) |
| 1291 | | { |
| 1292 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; |
| 1293 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 1; break; |
| 1294 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; |
| 1295 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break; |
| 1296 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break; |
| 1297 | | case CPUINFO_INT_PREVIOUSPC: info->i = ( cpustate->m_prev_pa << 6 ) | cpustate->m_prev_pc; break; |
| 1298 | | case CPUINFO_INT_PC: info->i = ( cpustate->m_ca << 10 ) | ( cpustate->m_pa << 6 ) | cpustate->m_pc; break; |
| 1299 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME( program_11bit_8 ); break; |
| 1300 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( data_7bit ); break; |
| 1301 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1100 ); break; |
| 1302 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms1100 ); break; |
| 1303 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS1100" ); break; |
| 1304 | | default: CPU_GET_INFO_CALL( tms_generic ); |
| 1305 | | } |
| 1102 | |
| 1103 | tms1100_cpu_device::tms1100_cpu_device(const machine_config &mconfig, device_type type, const char*name, const char *tag, device_t *owner, UINT32 clock, UINT16 o_mask, UINT16 r_mask) |
| 1104 | : tms1xxx_cpu_device( mconfig, type, name, tag, owner, clock, tms1100_default_decode, o_mask, r_mask, 6, 8, 3 |
| 1105 | , 11, ADDRESS_MAP_NAME( program_11bit_8 ), 7, ADDRESS_MAP_NAME( data_7bit ) ) |
| 1106 | { |
| 1306 | 1107 | } |
| 1307 | 1108 | |
| 1308 | 1109 | |
| 1309 | | CPU_GET_INFO( tms1300 ) |
| 1110 | offs_t tms1100_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 1310 | 1111 | { |
| 1311 | | switch(state) |
| 1312 | | { |
| 1313 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1300 ); break; |
| 1314 | | case CPUINFO_STR_NAME: strcpy( info->s, "TMS1300" ); break; |
| 1315 | | default: CPU_GET_INFO_CALL( tms1100 ); |
| 1316 | | } |
| 1112 | extern CPU_DISASSEMBLE( tms1100 ); |
| 1113 | return CPU_DISASSEMBLE_NAME(tms1100)(this, buffer, pc, oprom, opram, options); |
| 1317 | 1114 | } |
| 1318 | 1115 | |
| 1319 | 1116 | |
| 1320 | | DEFINE_LEGACY_CPU_DEVICE(TMS0980, tms0980); |
| 1117 | tms1300_cpu_device::tms1300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 1118 | : tms1100_cpu_device( mconfig, TMS1300, "TMS1300", tag, owner, clock, 0x00ff, 0xffff ) |
| 1119 | { |
| 1120 | } |
| 1321 | 1121 | |
| 1322 | | DEFINE_LEGACY_CPU_DEVICE(TMS1000, tms1000); |
| 1323 | | DEFINE_LEGACY_CPU_DEVICE(TMS1070, tms1070); |
| 1324 | | DEFINE_LEGACY_CPU_DEVICE(TMS1100, tms1100); |
| 1325 | | DEFINE_LEGACY_CPU_DEVICE(TMS1200, tms1200); |
| 1326 | | DEFINE_LEGACY_CPU_DEVICE(TMS1270, tms1270); |
| 1327 | | DEFINE_LEGACY_CPU_DEVICE(TMS1300, tms1300); |
trunk/src/emu/cpu/tms0980/tms0980.h
| r23640 | r23641 | |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | 11 | |
| 12 | | struct tms0980_config { |
| 13 | | /* O-output PLA configuration 5bit -> 8/11bit translation */ |
| 14 | | UINT16 o_pla[0x20]; |
| 15 | | devcb_read8 read_k; |
| 16 | | devcb_write16 write_o; /* tms1270 has 10 O-outputs */ |
| 17 | | devcb_write16 write_r; |
| 12 | #define MCFG_TMS1XXX_OUTPUT_PLA(_pla) \ |
| 13 | tms1xxx_cpu_device::set_output_pla(*device, _pla); |
| 14 | |
| 15 | #define MCFG_TMS1XXX_READ_K(_devcb) \ |
| 16 | tms1xxx_cpu_device::set_read_k(*device, DEVCB2_##_devcb); |
| 17 | |
| 18 | #define MCFG_TMS1XXX_WRITE_O(_devcb) \ |
| 19 | tms1xxx_cpu_device::set_write_o(*device, DEVCB2_##_devcb); |
| 20 | |
| 21 | #define MCFG_TMS1XXX_WRITE_R(_devcb) \ |
| 22 | tms1xxx_cpu_device::set_write_r(*device, DEVCB2_##_devcb); |
| 23 | |
| 24 | |
| 25 | class tms1xxx_cpu_device : public cpu_device |
| 26 | { |
| 27 | public: |
| 28 | // construction/destruction |
| 29 | tms1xxx_cpu_device( const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock |
| 30 | , const UINT32* decode_table, UINT16 o_mask, UINT16 r_mask, UINT8 pc_size, UINT8 byte_size, UINT8 x_bits |
| 31 | , int program_addrbus_width, address_map_constructor program, int data_addrbus_width, address_map_constructor data) |
| 32 | : cpu_device( mconfig, type, name, tag, owner, clock ) |
| 33 | , m_program_config("program", ENDIANNESS_BIG, byte_size > 8 ? 16 : 8, program_addrbus_width, 0, program ) |
| 34 | , m_data_config("data", ENDIANNESS_BIG, 8, data_addrbus_width, 0, data ) |
| 35 | , m_o_mask( o_mask ) |
| 36 | , m_r_mask( r_mask ) |
| 37 | , m_pc_size( pc_size ) |
| 38 | , m_byte_size( byte_size ) |
| 39 | , m_x_bits( x_bits ) |
| 40 | , m_decode_table( decode_table ) |
| 41 | , c_output_pla( NULL ) |
| 42 | , m_read_k( *this ) |
| 43 | , m_write_o( *this ) |
| 44 | , m_write_r( *this ) |
| 45 | { } |
| 46 | |
| 47 | // static configuration helpers |
| 48 | template<class _Object> static devcb2_base &set_read_k(device_t &device, _Object object) { return downcast<tms1xxx_cpu_device &>(device).m_read_k.set_callback(object); } |
| 49 | template<class _Object> static devcb2_base &set_write_o(device_t &device, _Object object) { return downcast<tms1xxx_cpu_device &>(device).m_write_o.set_callback(object); } |
| 50 | template<class _Object> static devcb2_base &set_write_r(device_t &device, _Object object) { return downcast<tms1xxx_cpu_device &>(device).m_write_r.set_callback(object); } |
| 51 | static void set_output_pla(device_t &device, const UINT16 *output_pla) { downcast<tms1xxx_cpu_device &>(device).c_output_pla = output_pla; } |
| 52 | |
| 53 | protected: |
| 54 | // device-level overrides |
| 55 | virtual void device_start(); |
| 56 | virtual void device_reset(); |
| 57 | |
| 58 | // device_execute_interface overrides |
| 59 | virtual UINT32 execute_min_cycles() const { return 1; } |
| 60 | virtual UINT32 execute_max_cycles() const { return 6; } |
| 61 | virtual UINT32 execute_input_lines() const { return 1; } |
| 62 | virtual void execute_run(); |
| 63 | |
| 64 | // device_memory_interface overrides |
| 65 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_DATA ) ? &m_data_config : NULL ); } |
| 66 | |
| 67 | // device_disasm_interface overrides |
| 68 | virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 69 | virtual UINT32 disasm_max_opcode_bytes() const { return 1; } |
| 70 | |
| 71 | void next_pc(); |
| 72 | void set_cki_bus(); |
| 73 | |
| 74 | address_space_config m_program_config; |
| 75 | address_space_config m_data_config; |
| 76 | |
| 77 | UINT8 m_prev_pc; /* previous program counter */ |
| 78 | UINT8 m_prev_pa; /* previous page address register */ |
| 79 | UINT8 m_pc; /* program counter is a 7 bit register on tms0980, 6 bit register on tms1000/1070/1200/1270/1100/1300 */ |
| 80 | UINT8 m_pa; /* page address register is a 4 bit register */ |
| 81 | UINT8 m_sr; /* subroutine return register is a 7 bit register */ |
| 82 | UINT8 m_pb; /* page buffer register is a 4 bit register */ |
| 83 | UINT8 m_a; /* Accumulator is a 4 bit register (?) */ |
| 84 | UINT8 m_x; /* X-register is a 2, 3, or 4 bit register */ |
| 85 | UINT8 m_y; /* Y-register is a 4 bit register */ |
| 86 | UINT8 m_dam; /* DAM register is a 4 bit register */ |
| 87 | UINT8 m_ca; /* Chapter address bit */ |
| 88 | UINT8 m_cb; /* Chapter buffer bit */ |
| 89 | UINT8 m_cs; /* Chapter subroutine bit */ |
| 90 | UINT16 m_r; |
| 91 | UINT8 m_o; |
| 92 | UINT8 m_cki_bus; /* CKI bus */ |
| 93 | UINT8 m_p; /* adder p-input */ |
| 94 | UINT8 m_n; /* adder n-input */ |
| 95 | UINT8 m_adder_result; /* adder result */ |
| 96 | UINT8 m_carry_in; /* carry in */ |
| 97 | UINT8 m_status; |
| 98 | UINT8 m_status_latch; |
| 99 | UINT8 m_special_status; |
| 100 | UINT8 m_call_latch; |
| 101 | UINT8 m_add_latch; |
| 102 | UINT8 m_branch_latch; |
| 103 | int m_subcycle; |
| 104 | UINT8 m_ram_address; |
| 105 | UINT16 m_ram_data; |
| 106 | UINT16 m_rom_address; |
| 107 | UINT16 m_opcode; |
| 108 | UINT32 m_decode; |
| 109 | int m_icount; |
| 110 | UINT16 m_o_mask; /* mask to determine the number of O outputs */ |
| 111 | UINT16 m_r_mask; /* mask to determine the number of R outputs */ |
| 112 | UINT8 m_pc_size; /* how bits in the PC register */ |
| 113 | UINT8 m_byte_size; /* 8 or 9 bit bytes */ |
| 114 | UINT8 m_x_bits; /* determine the number of bits in the X register */ |
| 115 | const UINT32 *m_decode_table; |
| 116 | address_space *m_program; |
| 117 | address_space *m_data; |
| 118 | |
| 119 | const UINT16 *c_output_pla; |
| 120 | devcb2_read8 m_read_k; |
| 121 | devcb2_write16 m_write_o; |
| 122 | devcb2_write16 m_write_r; |
| 123 | |
| 18 | 124 | }; |
| 19 | 125 | |
| 20 | 126 | |
| 127 | class tms0980_cpu_device : public tms1xxx_cpu_device |
| 128 | { |
| 129 | public: |
| 130 | tms0980_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 131 | |
| 132 | protected: |
| 133 | // device_state_interface overrides |
| 134 | void state_string_export(const device_state_entry &entry, astring &string); |
| 135 | |
| 136 | // device_disasm_interface overrides |
| 137 | virtual UINT32 disasm_min_opcode_bytes() const { return 2; } |
| 138 | virtual UINT32 disasm_max_opcode_bytes() const { return 2; } |
| 139 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 140 | }; |
| 141 | |
| 142 | |
| 143 | class tms1000_cpu_device : public tms1xxx_cpu_device |
| 144 | { |
| 145 | public: |
| 146 | tms1000_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 147 | tms1000_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT16 o_mask, UINT16 r_mask); |
| 148 | |
| 149 | protected: |
| 150 | // device_state_interface overrides |
| 151 | void state_string_export(const device_state_entry &entry, astring &string); |
| 152 | |
| 153 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 154 | }; |
| 155 | |
| 156 | |
| 157 | class tms1070_cpu_device : public tms1000_cpu_device |
| 158 | { |
| 159 | public: |
| 160 | tms1070_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 161 | }; |
| 162 | |
| 163 | |
| 164 | class tms1200_cpu_device : public tms1000_cpu_device |
| 165 | { |
| 166 | public: |
| 167 | tms1200_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 168 | }; |
| 169 | |
| 170 | |
| 171 | class tms1270_cpu_device : public tms1000_cpu_device |
| 172 | { |
| 173 | public: |
| 174 | tms1270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 175 | }; |
| 176 | |
| 177 | |
| 178 | class tms1100_cpu_device : public tms1xxx_cpu_device |
| 179 | { |
| 180 | public: |
| 181 | tms1100_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 182 | tms1100_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT16 o_mask, UINT16 r_mask); |
| 183 | |
| 184 | protected: |
| 185 | // device_state_interface overrides |
| 186 | void state_string_export(const device_state_entry &entry, astring &string); |
| 187 | |
| 188 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 189 | }; |
| 190 | |
| 191 | |
| 192 | class tms1300_cpu_device : public tms1100_cpu_device |
| 193 | { |
| 194 | public: |
| 195 | tms1300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 196 | }; |
| 197 | |
| 198 | |
| 21 | 199 | /* 9-bit family */ |
| 22 | | DECLARE_LEGACY_CPU_DEVICE(TMS0980, tms0980); |
| 200 | extern const device_type TMS0980; |
| 23 | 201 | |
| 24 | 202 | /* 8-bit family */ |
| 25 | | DECLARE_LEGACY_CPU_DEVICE(TMS1000, tms1000); |
| 26 | | DECLARE_LEGACY_CPU_DEVICE(TMS1070, tms1070); |
| 27 | | DECLARE_LEGACY_CPU_DEVICE(TMS1100, tms1100); |
| 28 | | DECLARE_LEGACY_CPU_DEVICE(TMS1200, tms1200); |
| 29 | | DECLARE_LEGACY_CPU_DEVICE(TMS1270, tms1270); |
| 30 | | DECLARE_LEGACY_CPU_DEVICE(TMS1300, tms1300); |
| 203 | extern const device_type TMS1000; |
| 204 | extern const device_type TMS1070; |
| 205 | extern const device_type TMS1200; |
| 206 | extern const device_type TMS1270; |
| 207 | extern const device_type TMS1100; |
| 208 | extern const device_type TMS1300; |
| 31 | 209 | |
| 32 | | extern CPU_DISASSEMBLE( tms0980 ); |
| 33 | | extern CPU_DISASSEMBLE( tms1000 ); |
| 34 | | extern CPU_DISASSEMBLE( tms1100 ); |
| 35 | 210 | |
| 36 | 211 | #endif /* _TMS0980_H_ */ |