trunk/src/emu/cpu/tms32031/tms32031.h
| r19125 | r19126 | |
| 69 | 69 | const int TMS3203X_DINT = 10; // DMA interrupt |
| 70 | 70 | const int TMS3203X_DINT0 = 10; // DMA 0 interrupt (32032 only) |
| 71 | 71 | const int TMS3203X_DINT1 = 11; // DMA 1 interrupt (32032 only) |
| 72 | const int TMS3203X_MCBL = 12; // Microcomputer/boot loader mode |
| 72 | 73 | |
| 73 | 74 | // register enumeration |
| 74 | 75 | enum |
| r19125 | r19126 | |
| 138 | 139 | |
| 139 | 140 | struct tms3203x_config |
| 140 | 141 | { |
| 141 | | UINT32 m_bootoffset; |
| 142 | bool m_mcbl_mode; |
| 142 | 143 | tms3203x_xf_func m_xf0_w; |
| 143 | 144 | tms3203x_xf_func m_xf1_w; |
| 144 | 145 | tms3203x_iack_func m_iack_w; |
| r19125 | r19126 | |
| 201 | 202 | virtual void device_start(); |
| 202 | 203 | virtual void device_reset(); |
| 203 | 204 | |
| 205 | virtual const rom_entry *device_rom_region() const; |
| 206 | |
| 204 | 207 | // device_execute_interface overrides |
| 205 | 208 | virtual UINT32 execute_min_cycles() const; |
| 206 | 209 | virtual UINT32 execute_max_cycles() const; |
| r19125 | r19126 | |
| 222 | 225 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 223 | 226 | |
| 224 | 227 | // memory helpers |
| 228 | DECLARE_DIRECT_UPDATE_MEMBER(direct_handler); |
| 225 | 229 | UINT32 ROPCODE(offs_t pc); |
| 226 | 230 | UINT32 RMEM(offs_t addr); |
| 227 | 231 | void WMEM(offs_t addr, UINT32 data); |
| 228 | 232 | |
| 229 | 233 | // misc helpers |
| 230 | 234 | void check_irqs(); |
| 231 | | UINT32 boot_loader(UINT32 boot_rom_addr); |
| 232 | 235 | void execute_one(); |
| 233 | 236 | void update_special(int dreg); |
| 234 | 237 | bool condition(int which); |
| r19125 | r19126 | |
| 798 | 801 | UINT16 m_irq_state; |
| 799 | 802 | bool m_delayed; |
| 800 | 803 | bool m_irq_pending; |
| 801 | | bool m_mcu_mode; |
| 802 | 804 | bool m_is_idling; |
| 803 | 805 | int m_icount; |
| 804 | 806 | |
| r19125 | r19126 | |
| 806 | 808 | device_irq_acknowledge_callback m_irq_callback; |
| 807 | 809 | address_space * m_program; |
| 808 | 810 | direct_read_data * m_direct; |
| 811 | UINT32 * m_bootrom; |
| 809 | 812 | |
| 810 | 813 | // tables |
| 811 | 814 | static void (tms3203x_device::*const s_tms32031ops[])(UINT32 op); |
trunk/src/emu/cpu/tms32031/tms32031.c
| r19125 | r19126 | |
| 119 | 119 | const device_type TMS32031 = &device_creator<tms32031_device>; |
| 120 | 120 | const device_type TMS32032 = &device_creator<tms32032_device>; |
| 121 | 121 | |
| 122 | |
| 122 | 123 | // internal memory maps |
| 123 | | static ADDRESS_MAP_START( internal_32031, AS_PROGRAM, 32, legacy_cpu_device ) |
| 124 | static ADDRESS_MAP_START( internal_32031, AS_PROGRAM, 32, tms32031_device ) |
| 124 | 125 | AM_RANGE(0x809800, 0x809fff) AM_RAM |
| 125 | 126 | ADDRESS_MAP_END |
| 126 | 127 | |
| 127 | | static ADDRESS_MAP_START( internal_32032, AS_PROGRAM, 32, legacy_cpu_device ) |
| 128 | static ADDRESS_MAP_START( internal_32032, AS_PROGRAM, 32, tms32032_device ) |
| 128 | 129 | AM_RANGE(0x87fe00, 0x87ffff) AM_RAM |
| 129 | 130 | ADDRESS_MAP_END |
| 130 | 131 | |
| 131 | 132 | |
| 133 | // ROM definitions for the internal boot loader programs |
| 134 | // (Using assembled versions until the code ROMs are extracted from both DSPs) |
| 135 | ROM_START( tms32031 ) |
| 136 | ROM_REGION(0x4000, "tms32031", 0) |
| 137 | ROM_LOAD( "c31boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(bddc2763) SHA1(96b2170ecee5bec5abaa1741bb2d3b6096ecc262) ) // Assembled from c31boot.asm (02-07-92) |
| 138 | ROM_END |
| 132 | 139 | |
| 140 | ROM_START( tms32032 ) |
| 141 | ROM_REGION(0x4000, "tms32032", 0) |
| 142 | ROM_LOAD( "c32boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(ecf84729) SHA1(4d32ead450f921f563514b061ea561a222283616) ) // Assembled from c32boot.asm (03-04-96) |
| 143 | ROM_END |
| 144 | |
| 145 | |
| 146 | |
| 133 | 147 | //************************************************************************** |
| 134 | 148 | // TMSREG REGISTER |
| 135 | 149 | //************************************************************************** |
| r19125 | r19126 | |
| 275 | 289 | m_irq_state(0), |
| 276 | 290 | m_delayed(false), |
| 277 | 291 | m_irq_pending(false), |
| 278 | | m_mcu_mode(false), |
| 279 | 292 | m_is_idling(false), |
| 280 | 293 | m_icount(0), |
| 281 | 294 | m_irq_callback(0), |
| 282 | 295 | m_program(0), |
| 283 | 296 | m_direct(0) |
| 284 | 297 | { |
| 285 | | m_bootoffset = 0; |
| 298 | m_mcbl_mode = false; |
| 286 | 299 | m_xf0_w = NULL; |
| 287 | 300 | m_xf1_w = NULL; |
| 288 | 301 | m_iack_w = NULL; |
| r19125 | r19126 | |
| 299 | 312 | } |
| 300 | 313 | |
| 301 | 314 | tms32031_device::tms32031_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 302 | | : tms3203x_device(mconfig, TMS32031, "TMS32031", tag, owner, clock, CHIP_TYPE_TMS32031, ADDRESS_MAP_NAME(internal_32031)) { } |
| 315 | : tms3203x_device(mconfig, TMS32031, "TMS32031", tag, owner, clock, CHIP_TYPE_TMS32031, ADDRESS_MAP_NAME(internal_32031)) |
| 316 | { |
| 317 | m_shortname = "tms32031"; |
| 318 | } |
| 303 | 319 | |
| 304 | 320 | tms32032_device::tms32032_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 305 | | : tms3203x_device(mconfig, TMS32032, "TMS32032", tag, owner, clock, CHIP_TYPE_TMS32032, ADDRESS_MAP_NAME(internal_32032)) { } |
| 321 | : tms3203x_device(mconfig, TMS32032, "TMS32032", tag, owner, clock, CHIP_TYPE_TMS32032, ADDRESS_MAP_NAME(internal_32032)) |
| 322 | { |
| 323 | m_shortname = "tms32032"; |
| 324 | } |
| 306 | 325 | |
| 307 | 326 | |
| 327 | DIRECT_UPDATE_MEMBER( tms3203x_device::direct_handler ) |
| 328 | { |
| 329 | // internal boot loader ROM |
| 330 | if (m_mcbl_mode && address < (0x1000 << 2)) |
| 331 | { |
| 332 | direct.explicit_configure(0x000000, 0x003fff, 0x003fff, m_bootrom); |
| 333 | return (offs_t)-1; |
| 334 | } |
| 335 | |
| 336 | return address; |
| 337 | } |
| 338 | |
| 339 | |
| 308 | 340 | //------------------------------------------------- |
| 309 | 341 | // ~tms3203x_device - destructor |
| 310 | 342 | //------------------------------------------------- |
| r19125 | r19126 | |
| 332 | 364 | |
| 333 | 365 | |
| 334 | 366 | //------------------------------------------------- |
| 367 | // rom_region - return a pointer to the device's |
| 368 | // internal ROM region |
| 369 | //------------------------------------------------- |
| 370 | |
| 371 | const rom_entry *tms3203x_device::device_rom_region() const |
| 372 | { |
| 373 | switch (m_chip_type) |
| 374 | { |
| 375 | default: |
| 376 | case CHIP_TYPE_TMS32031: return ROM_NAME( tms32031 ); |
| 377 | case CHIP_TYPE_TMS32032: return ROM_NAME( tms32032 ); |
| 378 | } |
| 379 | } |
| 380 | |
| 381 | //------------------------------------------------- |
| 335 | 382 | // ROPCODE - fetch an opcode |
| 336 | 383 | //------------------------------------------------- |
| 337 | 384 | |
| r19125 | r19126 | |
| 347 | 394 | |
| 348 | 395 | inline UINT32 tms3203x_device::RMEM(offs_t addr) |
| 349 | 396 | { |
| 397 | if (m_mcbl_mode && addr < 0x1000) |
| 398 | return m_bootrom[addr]; |
| 399 | |
| 350 | 400 | return m_program->read_dword(addr << 2); |
| 351 | 401 | } |
| 352 | 402 | |
| r19125 | r19126 | |
| 371 | 421 | m_program = &space(AS_PROGRAM); |
| 372 | 422 | m_direct = &m_program->direct(); |
| 373 | 423 | |
| 424 | // set up the internal boot loader ROM |
| 425 | m_bootrom = reinterpret_cast<UINT32*>(memregion(m_shortname)->base()); |
| 426 | m_direct->set_direct_update(direct_update_delegate(FUNC(tms3203x_device::direct_handler), this)); |
| 427 | |
| 374 | 428 | // save state |
| 375 | 429 | save_item(NAME(m_pc)); |
| 376 | 430 | for (int regnum = 0; regnum < 36; regnum++) |
| r19125 | r19126 | |
| 379 | 433 | save_item(NAME(m_irq_state)); |
| 380 | 434 | save_item(NAME(m_delayed)); |
| 381 | 435 | save_item(NAME(m_irq_pending)); |
| 382 | | save_item(NAME(m_mcu_mode)); |
| 383 | 436 | save_item(NAME(m_is_idling)); |
| 384 | 437 | |
| 385 | 438 | // register our state for the debugger |
| r19125 | r19126 | |
| 431 | 484 | |
| 432 | 485 | void tms3203x_device::device_reset() |
| 433 | 486 | { |
| 434 | | // if we have a config struct, get the boot ROM address |
| 435 | | if (m_bootoffset != 0) |
| 436 | | { |
| 437 | | m_mcu_mode = true; |
| 438 | | m_pc = boot_loader(m_bootoffset); |
| 439 | | } |
| 440 | | else |
| 441 | | { |
| 442 | | m_mcu_mode = false; |
| 443 | | m_pc = RMEM(0); |
| 444 | | } |
| 487 | m_pc = RMEM(0); |
| 445 | 488 | |
| 446 | 489 | // reset some registers |
| 447 | 490 | IREG(TMR_IE) = 0; |
| r19125 | r19126 | |
| 449 | 492 | IREG(TMR_ST) = 0; |
| 450 | 493 | IREG(TMR_IOF) = 0; |
| 451 | 494 | |
| 495 | // update IF with the external interrupt state (required for boot loader operation) |
| 496 | IREG(TMR_IF) |= m_irq_state & 0x0f; |
| 497 | |
| 452 | 498 | // reset internal stuff |
| 453 | 499 | m_delayed = m_irq_pending = m_is_idling = false; |
| 454 | 500 | } |
| r19125 | r19126 | |
| 718 | 764 | |
| 719 | 765 | UINT32 tms3203x_device::execute_input_lines() const |
| 720 | 766 | { |
| 721 | | return 11; |
| 767 | return (m_chip_type == CHIP_TYPE_TMS32032) ? 13 : 12; |
| 722 | 768 | } |
| 723 | 769 | |
| 724 | 770 | |
| r19125 | r19126 | |
| 729 | 775 | void tms3203x_device::execute_set_input(int inputnum, int state) |
| 730 | 776 | { |
| 731 | 777 | // ignore anything out of range |
| 732 | | if (inputnum >= 12) |
| 778 | if (inputnum >= 13) |
| 733 | 779 | return; |
| 734 | 780 | |
| 781 | if (inputnum == TMS3203X_MCBL) |
| 782 | { |
| 783 | // switch between microcomputer/boot loader and microprocessor modes |
| 784 | m_mcbl_mode = (state == ASSERT_LINE); |
| 785 | m_direct->force_update(); |
| 786 | return; |
| 787 | } |
| 788 | |
| 735 | 789 | // update the external state |
| 736 | 790 | UINT16 intmask = 1 << inputnum; |
| 737 | 791 | if (state == ASSERT_LINE) |
| r19125 | r19126 | |
| 830 | 884 | } |
| 831 | 885 | |
| 832 | 886 | |
| 833 | | //------------------------------------------------- |
| 834 | | // boot_loader - reset the state of the system |
| 835 | | // by simulating the internal boot loader |
| 836 | | //------------------------------------------------- |
| 837 | | |
| 838 | | UINT32 tms3203x_device::boot_loader(UINT32 boot_rom_addr) |
| 839 | | { |
| 840 | | // read the size of the data |
| 841 | | UINT32 bits = RMEM(boot_rom_addr); |
| 842 | | if (bits != 8 && bits != 16 && bits != 32) |
| 843 | | return 0; |
| 844 | | UINT32 datamask = 0xffffffffUL >> (32 - bits); |
| 845 | | UINT32 advance = 32 / bits; |
| 846 | | boot_rom_addr += advance; |
| 847 | | |
| 848 | | // read the control register |
| 849 | | UINT32 control = RMEM(boot_rom_addr++) & datamask; |
| 850 | | for (int i = 1; i < advance; i++) |
| 851 | | control |= (RMEM(boot_rom_addr++) & datamask) << (bits * i); |
| 852 | | |
| 853 | | // now parse the data |
| 854 | | UINT32 start_offset = 0; |
| 855 | | bool first = true; |
| 856 | | while (1) |
| 857 | | { |
| 858 | | // read the length of this section |
| 859 | | UINT32 len = RMEM(boot_rom_addr++) & datamask; |
| 860 | | for (int i = 1; i < advance; i++) |
| 861 | | len |= (RMEM(boot_rom_addr++) & datamask) << (bits * i); |
| 862 | | |
| 863 | | // stop at 0 |
| 864 | | if (len == 0) |
| 865 | | return start_offset; |
| 866 | | |
| 867 | | // read the destination offset of this section |
| 868 | | UINT32 offs = RMEM(boot_rom_addr++) & datamask; |
| 869 | | for (int i = 1; i < advance; i++) |
| 870 | | offs |= (RMEM(boot_rom_addr++) & datamask) << (bits * i); |
| 871 | | |
| 872 | | // if this is the first block, that's where we boot to |
| 873 | | if (first) |
| 874 | | { |
| 875 | | start_offset = offs; |
| 876 | | first = false; |
| 877 | | } |
| 878 | | |
| 879 | | // now copy the data |
| 880 | | while (len--) |
| 881 | | { |
| 882 | | // extract the 32-bit word |
| 883 | | UINT32 data = RMEM(boot_rom_addr++) & datamask; |
| 884 | | for (int i = 1; i < advance; i++) |
| 885 | | data |= (RMEM(boot_rom_addr++) & datamask) << (bits * i); |
| 886 | | |
| 887 | | // write it out |
| 888 | | WMEM(offs++, data); |
| 889 | | } |
| 890 | | } |
| 891 | | } |
| 892 | | |
| 893 | | |
| 894 | 887 | //************************************************************************** |
| 895 | 888 | // CORE OPCODES |
| 896 | 889 | //************************************************************************** |