diff options
Diffstat (limited to 'trunk/src/emu/cpu/sc61860/sc61860.c')
-rw-r--r-- | trunk/src/emu/cpu/sc61860/sc61860.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/sc61860/sc61860.c b/trunk/src/emu/cpu/sc61860/sc61860.c new file mode 100644 index 00000000000..b943bbef7d6 --- /dev/null +++ b/trunk/src/emu/cpu/sc61860/sc61860.c @@ -0,0 +1,252 @@ +/***************************************************************************** + * + * sc61860.c + * portable sharp 61860 emulator interface + * (sharp pocket computers) + * + * Copyright Peter Trauner, all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * peter.trauner@jk.uni-linz.ac.at + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * History of changes: + * 29.7.2001 Several changes listed below taken by Mario Konegger + * (konegger@itp.tu-graz.ac.at) + * Added 0x7f to set_reg, to prevent p,q,r, overflow. + * Changed 512ms timerinterval from 256 to 128, thus the + * duration of one period is 512ms. + * Extended execute procudure with HLT-mode of CPU. + *****************************************************************************/ + +#include "emu.h" +#include "debugger.h" + +#include "sc61860.h" +#include "sc.h" + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +/**************************************************************************** + * The 61860 registers. + ****************************************************************************/ +typedef struct _sc61860_state sc61860_state; +struct _sc61860_state +{ + sc61860_cpu_core *config; + UINT8 p, q, r; //7 bits only? + + UINT8 c; // port c, used for HLT. + UINT8 d, h; + UINT16 oldpc, pc, dp; + + int carry, zero; + + struct { int t2ms, t512ms; int count; } timer; + + legacy_cpu_device *device; + address_space *program; + direct_read_data *direct; + int icount; + UINT8 ram[0x100]; // internal special ram, should be 0x60, 0x100 to avoid memory corruption for now +}; + +INLINE sc61860_state *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == SC61860); + return (sc61860_state *)downcast<legacy_cpu_device *>(device)->token(); +} + +UINT8 *sc61860_internal_ram(device_t *device) +{ + sc61860_state *cpustate = get_safe_token(device); + return cpustate->ram; +} + +static TIMER_CALLBACK(sc61860_2ms_tick) +{ + sc61860_state *cpustate = (sc61860_state *)ptr; + if (--cpustate->timer.count == 0) + { + cpustate->timer.count = 128; + cpustate->timer.t512ms = !cpustate->timer.t512ms; + } + cpustate->timer.t2ms = !cpustate->timer.t2ms; +} + +/*************************************************************** + * include the opcode macros, functions and tables + ***************************************************************/ +#include "scops.c" +#include "sctable.c" + +static CPU_RESET( sc61860 ) +{ + sc61860_state *cpustate = get_safe_token(device); + cpustate->timer.t2ms=0; + cpustate->timer.t512ms=0; + cpustate->timer.count=256; + cpustate->pc=0; +} + +static CPU_INIT( sc61860 ) +{ + sc61860_state *cpustate = get_safe_token(device); + cpustate->config = (sc61860_cpu_core *) device->static_config(); + device->machine().scheduler().timer_pulse(attotime::from_hz(500), FUNC(sc61860_2ms_tick), 0, cpustate); + cpustate->device = device; + cpustate->program = device->space(AS_PROGRAM); + cpustate->direct = &cpustate->program->direct(); +} + +static CPU_EXECUTE( sc61860 ) +{ + sc61860_state *cpustate = get_safe_token(device); + + do + { + cpustate->oldpc = cpustate->pc; + + debugger_instruction_hook(device, cpustate->pc); + + sc61860_instruction(cpustate); + +#if 0 + /* Are we in HLT-mode? */ + if (cpustate->c & 4) + { + if ((cpustate->config && cpustate->config->ina && (cpustate->config->ina(cpustate)!=0)) || cpustate->timer.t512ms) + { + cpustate->c&=0xfb; + if (cpustate->config->outc) cpustate->config->outc(cpustate->c); + } + cpustate->icount-=4; + } + else if(cpustate->c & 8) {} + + else sc61860_instruction(cpustate); +#endif + + } while (cpustate->icount > 0); +} + + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static CPU_SET_INFO( sc61860 ) +{ + sc61860_state *cpustate = get_safe_token(device); + switch (state) + { + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + SC61860_PC: cpustate->pc = info->i; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + SC61860_R: cpustate->r = info->i & 0x7F; break; + case CPUINFO_INT_REGISTER + SC61860_DP: cpustate->dp = info->i; break; + case CPUINFO_INT_REGISTER + SC61860_P: cpustate->p = info->i & 0x7F; break; + case CPUINFO_INT_REGISTER + SC61860_Q: cpustate->q = info->i & 0x7F; break; + case CPUINFO_INT_REGISTER + SC61860_CARRY: cpustate->carry = info->i; break; + case CPUINFO_INT_REGISTER + SC61860_ZERO: cpustate->zero = info->i; break; + } +} + + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +CPU_GET_INFO( sc61860 ) +{ + sc61860_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sc61860_state); break; + case CPUINFO_INT_INPUT_LINES: info->i = 0; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 2; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; + + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->oldpc; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + SC61860_PC: info->i = cpustate->pc; break; + case CPUINFO_INT_SP: + case CPUINFO_INT_REGISTER + SC61860_R: info->i = cpustate->r; break; + case CPUINFO_INT_REGISTER + SC61860_DP: info->i = cpustate->dp; break; + case CPUINFO_INT_REGISTER + SC61860_P: info->i = cpustate->p; break; + case CPUINFO_INT_REGISTER + SC61860_Q: info->i = cpustate->q; break; + case CPUINFO_INT_REGISTER + SC61860_CARRY: info->i = cpustate->carry; break; + case CPUINFO_INT_REGISTER + SC61860_ZERO: info->i = cpustate->zero; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sc61860); break; + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sc61860); break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sc61860); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sc61860); break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sc61860); break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "SC61860"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "SC61860"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.0beta"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Peter Trauner, all rights reserved."); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c", cpustate->zero?'Z':'.', cpustate->carry ? 'C':'.'); + break; + + case CPUINFO_STR_REGISTER + SC61860_PC: sprintf(info->s, "PC:%.4x", cpustate->pc);break; + case CPUINFO_STR_REGISTER + SC61860_DP: sprintf(info->s, "DP:%.4x", cpustate->dp);break; + case CPUINFO_STR_REGISTER + SC61860_P: sprintf(info->s, "P:%.2x", cpustate->p);break; + case CPUINFO_STR_REGISTER + SC61860_Q: sprintf(info->s, "Q:%.2x", cpustate->q);break; + case CPUINFO_STR_REGISTER + SC61860_R: sprintf(info->s, "R:%.2x", cpustate->r);break; + case CPUINFO_STR_REGISTER + SC61860_I: sprintf(info->s, "I:%.2x", cpustate->ram[I]);break; + case CPUINFO_STR_REGISTER + SC61860_J: sprintf(info->s, "J:%.2x", cpustate->ram[J]);break; + case CPUINFO_STR_REGISTER + SC61860_K: sprintf(info->s, "K:%.2x", cpustate->ram[K]);break; + case CPUINFO_STR_REGISTER + SC61860_L: sprintf(info->s, "L:%.2x", cpustate->ram[L]);break; + case CPUINFO_STR_REGISTER + SC61860_V: sprintf(info->s, "V:%.2x", cpustate->ram[V]);break; + case CPUINFO_STR_REGISTER + SC61860_W: sprintf(info->s, "W:%.2x", cpustate->ram[W]);break; + case CPUINFO_STR_REGISTER + SC61860_H: sprintf(info->s, "W:%.2x", cpustate->h);break; + case CPUINFO_STR_REGISTER + SC61860_BA: sprintf(info->s, "BA:%.2x%.2x", cpustate->ram[B], cpustate->ram[A]);break; + case CPUINFO_STR_REGISTER + SC61860_X: sprintf(info->s, "X: %.2x%.2x", cpustate->ram[XH], cpustate->ram[XL]);break; + case CPUINFO_STR_REGISTER + SC61860_Y: sprintf(info->s, "Y: %.2x%.2x", cpustate->ram[YH], cpustate->ram[YL]);break; + case CPUINFO_STR_REGISTER + SC61860_CARRY: sprintf(info->s, "Carry: %d", cpustate->carry);break; + case CPUINFO_STR_REGISTER + SC61860_ZERO: sprintf(info->s, "Zero: %d", cpustate->zero);break; + } +} + +DEFINE_LEGACY_CPU_DEVICE(SC61860, sc61860); |