diff options
Diffstat (limited to 'trunk/src/emu/devcpu.c')
-rw-r--r-- | trunk/src/emu/devcpu.c | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/trunk/src/emu/devcpu.c b/trunk/src/emu/devcpu.c new file mode 100644 index 00000000000..0442b4746f5 --- /dev/null +++ b/trunk/src/emu/devcpu.c @@ -0,0 +1,484 @@ +/*************************************************************************** + + devcpu.c + + CPU device definitions. + +**************************************************************************** + + Copyright Aaron Giles + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name 'MAME' nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +***************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include <ctype.h> + + +//************************************************************************** +// CPU RUNNING DEVICE +//************************************************************************** + +//------------------------------------------------- +// cpu_device - constructor +//------------------------------------------------- + +cpu_device::cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, type, name, tag, owner, clock), + device_execute_interface(mconfig, *this), + device_memory_interface(mconfig, *this), + device_state_interface(mconfig, *this), + device_disasm_interface(mconfig, *this) +{ +} + + +//------------------------------------------------- +// cpu_device - destructor +//------------------------------------------------- + +cpu_device::~cpu_device() +{ +} + + +//------------------------------------------------- +// legacy_cpu_device - constructor +//------------------------------------------------- + +legacy_cpu_device::legacy_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, cpu_get_info_func get_info) + : cpu_device(mconfig, type, "CPU", tag, owner, clock), + m_get_info(get_info), + m_token(NULL), + m_set_info(reinterpret_cast<cpu_set_info_func>(get_legacy_fct(CPUINFO_FCT_SET_INFO))), + m_execute(reinterpret_cast<cpu_execute_func>(get_legacy_fct(CPUINFO_FCT_EXECUTE))), + m_burn(reinterpret_cast<cpu_burn_func>(get_legacy_fct(CPUINFO_FCT_BURN))), + m_translate(reinterpret_cast<cpu_translate_func>(get_legacy_fct(CPUINFO_FCT_TRANSLATE))), + m_read(reinterpret_cast<cpu_read_func>(get_legacy_fct(CPUINFO_FCT_READ))), + m_write(reinterpret_cast<cpu_write_func>(get_legacy_fct(CPUINFO_FCT_WRITE))), + m_readop(reinterpret_cast<cpu_readop_func>(get_legacy_fct(CPUINFO_FCT_READOP))), + m_disassemble(reinterpret_cast<cpu_disassemble_func>(get_legacy_fct(CPUINFO_FCT_DISASSEMBLE))), + m_state_import(reinterpret_cast<cpu_state_io_func>(get_legacy_fct(CPUINFO_FCT_IMPORT_STATE))), + m_state_export(reinterpret_cast<cpu_state_io_func>(get_legacy_fct(CPUINFO_FCT_EXPORT_STATE))), + m_string_export(reinterpret_cast<cpu_string_io_func>(get_legacy_fct(CPUINFO_FCT_EXPORT_STRING))), + m_exit(reinterpret_cast<cpu_exit_func>(get_legacy_fct(CPUINFO_FCT_EXIT))), + m_using_legacy_state(false), + m_inited(false) +{ + // build up our address spaces; legacy devices don't have logical spaces + memset(m_space_config, 0, sizeof(m_space_config)); + for (address_spacenum spacenum = AS_0; spacenum < ARRAY_LENGTH(m_space_config); spacenum++) + { + m_space_config[spacenum].m_name = (spacenum == 1) ? "data" : (spacenum == 2) ? "i/o" : "program"; + m_space_config[spacenum].m_endianness = static_cast<endianness_t>(get_legacy_int(DEVINFO_INT_ENDIANNESS)); + m_space_config[spacenum].m_databus_width = get_legacy_int(DEVINFO_INT_DATABUS_WIDTH + spacenum); + m_space_config[spacenum].m_addrbus_width = get_legacy_int(DEVINFO_INT_ADDRBUS_WIDTH + spacenum); + m_space_config[spacenum].m_addrbus_shift = get_legacy_int(DEVINFO_INT_ADDRBUS_SHIFT + spacenum); + m_space_config[spacenum].m_logaddr_width = get_legacy_int(CPUINFO_INT_LOGADDR_WIDTH + spacenum); + if (m_space_config[spacenum].m_logaddr_width == 0) + m_space_config[spacenum].m_logaddr_width = m_space_config[spacenum].m_addrbus_width; + m_space_config[spacenum].m_page_shift = get_legacy_int(CPUINFO_INT_PAGE_SHIFT + spacenum); + m_space_config[spacenum].m_internal_map = reinterpret_cast<address_map_constructor>(get_legacy_fct(DEVINFO_PTR_INTERNAL_MEMORY_MAP + spacenum)); + m_space_config[spacenum].m_default_map = reinterpret_cast<address_map_constructor>(get_legacy_fct(DEVINFO_PTR_DEFAULT_MEMORY_MAP + spacenum)); + } + + // set the real name + m_name = get_legacy_string(DEVINFO_STR_NAME); + m_shortname = get_legacy_string(DEVINFO_STR_SHORTNAME); + m_searchpath = m_shortname; + + memset(&m_partial_frame_period, 0, sizeof(m_partial_frame_period)); + + int tokenbytes = get_legacy_int(CPUINFO_INT_CONTEXT_SIZE); + if (tokenbytes == 0) + throw emu_fatalerror("Device %s specifies a 0 context size!\n", tag); + + // allocate memory for the token + m_token = global_alloc_array_clear(UINT8, tokenbytes); +} + + +//------------------------------------------------- +// legacy_cpu_device - destructor +//------------------------------------------------- + +legacy_cpu_device::~legacy_cpu_device() +{ + global_free(m_token); +} + + +//------------------------------------------------- +// device_start - start up the device +//------------------------------------------------- + +void legacy_cpu_device::device_start() +{ + // standard init + cpu_init_func init = reinterpret_cast<cpu_init_func>(get_legacy_fct(CPUINFO_FCT_INIT)); + (*init)(this, static_standard_irq_callback); + m_inited = true; + + // fetch information about the CPU states + if (m_state_list.count() == 0) + { + m_using_legacy_state = true; + for (int index = 0; index < MAX_REGS; index++) + { + const char *string = get_legacy_string(CPUINFO_STR_REGISTER + index); + if (strchr(string, ':') != NULL) + { + astring tempstr(string); + bool noshow = (tempstr.chr(0, '~') == 0); + if (noshow) + tempstr.substr(1, -1); + + int colon = tempstr.chr(0, ':'); + int length = tempstr.len() - colon - 1; + + tempstr.substr(0, colon).trimspace(); + + astring formatstr; + formatstr.printf("%%%ds", length); + device_state_entry &entry = state_add(index, tempstr, m_state_io).callimport().callexport().formatstr(formatstr); + if (noshow) + entry.noshow(); + } + } + state_add(STATE_GENPC, "curpc", m_state_io).callimport().callexport().formatstr("%8s").noshow(); + state_add(STATE_GENPCBASE, "curpcbase", m_state_io).callimport().callexport().formatstr("%8s").noshow(); + + const char *string = get_legacy_string(CPUINFO_STR_FLAGS); + if (string != NULL && string[0] != 0) + { + astring flagstr; + flagstr.printf("%%%ds", strlen(string)); + state_add(STATE_GENFLAGS, "GENFLAGS", m_state_io).callimport().callexport().formatstr(flagstr).noshow(); + } + } + + // get our icount pointer + m_icountptr = reinterpret_cast<int *>(get_legacy_ptr(CPUINFO_PTR_INSTRUCTION_COUNTER)); + assert(m_icountptr != 0); + *m_icountptr = 0; +} + + +//------------------------------------------------- +// device_reset - reset up the device +//------------------------------------------------- + +void legacy_cpu_device::device_reset() +{ + cpu_reset_func reset = reinterpret_cast<cpu_reset_func>(get_legacy_fct(CPUINFO_FCT_RESET)); + if (reset != NULL) + (*reset)(this); +} + + +//------------------------------------------------- +// device_stop - clean up before the machine goes +// away +//------------------------------------------------- + +void legacy_cpu_device::device_stop() +{ + // call the CPU's exit function if present + if (m_inited && m_exit != NULL) + (*m_exit)(this); +} + + +//------------------------------------------------- +// execute_clocks_to_cycles - convert the raw +// clock into cycles per second +//------------------------------------------------- + +UINT64 legacy_cpu_device::execute_clocks_to_cycles(UINT64 clocks) const +{ + UINT32 multiplier = get_legacy_int(CPUINFO_INT_CLOCK_MULTIPLIER); + UINT32 divider = get_legacy_int(CPUINFO_INT_CLOCK_DIVIDER); + + if (multiplier == 0) multiplier = 1; + if (divider == 0) divider = 1; + + return (clocks * multiplier + divider - 1) / divider; +} + + +//------------------------------------------------- +// execute_cycles_to_clocks - convert a cycle +// count back to raw clocks +//------------------------------------------------- + +UINT64 legacy_cpu_device::execute_cycles_to_clocks(UINT64 cycles) const +{ + UINT32 multiplier = get_legacy_int(CPUINFO_INT_CLOCK_MULTIPLIER); + UINT32 divider = get_legacy_int(CPUINFO_INT_CLOCK_DIVIDER); + + if (multiplier == 0) multiplier = 1; + if (divider == 0) divider = 1; + + return (cycles * divider + multiplier - 1) / multiplier; +} + + +//------------------------------------------------- +// execute_run - execute for the provided number +// of cycles +//------------------------------------------------- + +void legacy_cpu_device::execute_run() +{ + (*m_execute)(this); +} + + +//------------------------------------------------- +// execute_burn - burn the requested number of cycles +//------------------------------------------------- + +void legacy_cpu_device::execute_burn(INT32 cycles) +{ + if (m_burn != NULL) + (*m_burn)(this, cycles); +} + + +//------------------------------------------------- +// memory_translate - perform address translation +// on the provided address +//------------------------------------------------- + +bool legacy_cpu_device::memory_translate(address_spacenum spacenum, int intention, offs_t &address) +{ + if (m_translate != NULL) + return (*m_translate)(this, spacenum, intention, &address) ? true : false; + return true; +} + + +//------------------------------------------------- +// memory_read - read device memory, allowing for +// device specific overrides +//------------------------------------------------- + +bool legacy_cpu_device::memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value) +{ + if (m_read != NULL) + return (*m_read)(this, spacenum, offset, size, &value) ? true : false; + return false; +} + + +//------------------------------------------------- +// memory_write - write device memory, allowing +// for device specific overrides +//------------------------------------------------- + +bool legacy_cpu_device::memory_write(address_spacenum spacenum, offs_t offset, int size, UINT64 value) +{ + if (m_write != NULL) + return (*m_write)(this, spacenum, offset, size, value) ? true : false; + return false; +} + + +//------------------------------------------------- +// memory_read - read device opcode memory, +// allowing for device specific overrides +//------------------------------------------------- + +bool legacy_cpu_device::memory_readop(offs_t offset, int size, UINT64 &value) +{ + if (m_readop != NULL) + return (*m_readop)(this, offset, size, &value) ? true : false; + return false; +} + + +//------------------------------------------------- +// debug_setup - set up any device-specific +// debugging commands or state +//------------------------------------------------- + +void legacy_cpu_device::device_debug_setup() +{ + cpu_debug_init_func init = reinterpret_cast<cpu_debug_init_func>(get_legacy_fct(CPUINFO_FCT_DEBUG_INIT)); + if (init != NULL) + (*init)(this); +} + + +//------------------------------------------------- +// disassemble - disassemble the provided opcode +// data to a buffer +//------------------------------------------------- + +offs_t legacy_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + // if we have a callback, just use that + if (m_disassemble != NULL) + return (*m_disassemble)(this, buffer, pc, oprom, opram, options); + + // if not, just output vanilla bytes + int width = min_opcode_bytes(); + switch (width) + { + case 1: + default: + sprintf(buffer, "$%02X", *(UINT8 *)oprom); + break; + + case 2: + sprintf(buffer, "$%04X", *(UINT16 *)oprom); + break; + + case 4: + sprintf(buffer, "$%08X", *(UINT32 *)oprom); + break; + + case 8: + sprintf(buffer, "$%08X%08X", (UINT32)(*(UINT64 *)oprom >> 32), (UINT32)(*(UINT64 *)oprom >> 0)); + break; + } + return width; +} + + +//------------------------------------------------- +// get_legacy_int - return a legacy integer value +//------------------------------------------------- + +INT64 legacy_cpu_device::get_legacy_int(UINT32 state) const +{ + cpuinfo info = { 0 }; + (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info); + return info.i; +} + + +//------------------------------------------------- +// get_legacy_ptr - return a legacy pointer value +//------------------------------------------------- + +void *legacy_cpu_device::get_legacy_ptr(UINT32 state) const +{ + cpuinfo info = { 0 }; + (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info); + return info.p; +} + + +//------------------------------------------------- +// get_legacy_fct - return a legacy function value +//------------------------------------------------- + +genf *legacy_cpu_device::get_legacy_fct(UINT32 state) const +{ + cpuinfo info = { 0 }; + (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info); + return info.f; +} + + +//------------------------------------------------- +// get_legacy_string - return a legacy +// string value +//------------------------------------------------- + +const char *legacy_cpu_device::get_legacy_string(UINT32 state) const +{ + cpuinfo info; + info.s = get_temp_string_buffer(); + (*m_get_info)(const_cast<legacy_cpu_device *>(this), state, &info); + return info.s; +} + + +//------------------------------------------------- +// set_legacy_int - call the get info function +// to set an integer value +//------------------------------------------------- + +void legacy_cpu_device::set_legacy_int(UINT32 state, INT64 value) +{ + cpuinfo info = { 0 }; + info.i = value; + (*m_set_info)(this, state, &info); +} + + + +void legacy_cpu_device::state_import(const device_state_entry &entry) +{ + if (m_using_legacy_state) + { + if (entry.index() == STATE_GENFLAGS) + ; // do nothing + else + set_legacy_int(CPUINFO_INT_REGISTER + entry.index(), m_state_io); + } + else if (m_state_import != NULL) + (*m_state_import)(this, entry); +} + + +void legacy_cpu_device::state_export(const device_state_entry &entry) +{ + if (m_using_legacy_state) + { + if (entry.index() == STATE_GENFLAGS) + { + const char *temp = get_legacy_string(CPUINFO_STR_FLAGS); + m_state_io = 0; + while (*temp != 0) + m_state_io = ((m_state_io << 5) | (m_state_io >> (64-5))) ^ *temp++; + } + else + m_state_io = get_legacy_int(CPUINFO_INT_REGISTER + entry.index()); + } + else if (m_state_export != NULL) + (*m_state_export)(this, entry); +} + + +void legacy_cpu_device::state_string_export(const device_state_entry &entry, astring &string) +{ + if (m_using_legacy_state) + { + if (entry.index() == STATE_GENFLAGS) + string.cpy(get_legacy_string(CPUINFO_STR_FLAGS)); + else + string.cpy(strchr(get_legacy_string(CPUINFO_STR_REGISTER + entry.index()), ':') + 1); + } + else if (m_string_export != NULL) + (*m_string_export)(this, entry, string); +} |