From 3a082a644f6fc1fcd0c5760e96572870ae26af3f Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Thu, 13 Mar 2008 15:35:17 +0000 Subject: [PATCH] From: notaz [mailto:notasas@gmail.com] Subject: patch for SVP (Sega Virtua Processor) emulation hello, this patch adds support for Sega Virtua Processor, to run Genesis/MegaDrive version of Virtua Racing, intended to be used by MESS. It consists of a CPU core SSP1601, and updates in megadriv.c: * SSP1601 replaces SSP1610, as it has been confirmed by Stiletto and other sources that SVP actually contains SSP1601. The current SSP1610 is placeholder only (nearly completely unimplemented) anyway. * Changes in megadriv.c add a new driver for Genesis/MegaDrive+SVP combination, also add SVP memory controller logic and memory map. The diff has already been reviewed by Reip and SSP1610 removal was one of his suggestions (SSP1610 is not used by any drivers). --- .gitattributes | 6 +- src/emu/cpu/cpu.mak | 16 +- src/emu/cpu/ssp1601/ssp1601.c | 918 +++++++++++++++++++++++++++++++++ src/emu/cpu/ssp1601/ssp1601.h | 24 + src/emu/cpu/ssp1601/ssp1601d.c | 290 +++++++++++ src/emu/cpu/ssp1610/ssp1610.c | 870 ------------------------------- src/emu/cpu/ssp1610/ssp1610.h | 16 - src/emu/cpu/ssp1610/ssp1610d.c | 532 ------------------- src/emu/cpuexec.h | 2 +- src/emu/cpuintrf.c | 6 +- src/mame/drivers/megadriv.c | 432 +++++++++++++++- src/mame/drivers/megadriv.h | 3 + src/mame/mame.mak | 2 +- 13 files changed, 1675 insertions(+), 1442 deletions(-) create mode 100644 src/emu/cpu/ssp1601/ssp1601.c create mode 100644 src/emu/cpu/ssp1601/ssp1601.h create mode 100644 src/emu/cpu/ssp1601/ssp1601d.c delete mode 100644 src/emu/cpu/ssp1610/ssp1610.c delete mode 100644 src/emu/cpu/ssp1610/ssp1610.h delete mode 100644 src/emu/cpu/ssp1610/ssp1610d.c diff --git a/.gitattributes b/.gitattributes index a5c7a0cb30b..6ee74365c28 100644 --- a/.gitattributes +++ b/.gitattributes @@ -355,9 +355,9 @@ src/emu/cpu/spc700/spc700.c svneol=native#text/plain src/emu/cpu/spc700/spc700.h svneol=native#text/plain src/emu/cpu/spc700/spc700ds.c svneol=native#text/plain src/emu/cpu/spc700/spc700ds.h svneol=native#text/plain -src/emu/cpu/ssp1610/ssp1610.c svneol=native#text/plain -src/emu/cpu/ssp1610/ssp1610.h svneol=native#text/plain -src/emu/cpu/ssp1610/ssp1610d.c svneol=native#text/plain +src/emu/cpu/ssp1601/ssp1601.c svneol=native#text/plain +src/emu/cpu/ssp1601/ssp1601.h svneol=native#text/plain +src/emu/cpu/ssp1601/ssp1601d.c svneol=native#text/plain src/emu/cpu/t11/t11.c svneol=native#text/plain src/emu/cpu/t11/t11.h svneol=native#text/plain src/emu/cpu/t11/t11dasm.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 57bc4264f64..2054b45c8d5 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -1390,19 +1390,19 @@ $(CPUOBJ)/mips/psx.o: $(CPUSRC)/mips/psx.c \ #------------------------------------------------- -# SSP1610 +# SSP1601 #------------------------------------------------- -CPUDEFS += -DHAS_SSP1610=$(if $(filter SSP1610,$(CPUS)),1,0) +CPUDEFS += -DHAS_SSP1601=$(if $(filter SSP1601,$(CPUS)),1,0) -ifneq ($(filter SSP1610,$(CPUS)),) -OBJDIRS += $(CPUOBJ)/ssp1610 -CPUOBJS += $(CPUOBJ)/ssp1610/ssp1610.o -DBGOBJS += $(CPUOBJ)/ssp1610/ssp1610d.o +ifneq ($(filter SSP1601,$(CPUS)),) +OBJDIRS += $(CPUOBJ)/ssp1601 +CPUOBJS += $(CPUOBJ)/ssp1601/ssp1601.o +DBGOBJS += $(CPUOBJ)/ssp1601/ssp1601d.o endif -$(CPUOBJ)/ssp1610/ssp1610.o: $(CPUSRC)/ssp1610/ssp1610.c \ - $(CPUSRC)/ssp1610/ssp1610.h +$(CPUOBJ)/ssp1610/ssp1601.o: $(CPUSRC)/ssp1601/ssp1601.c \ + $(CPUSRC)/ssp1610/ssp1601.h diff --git a/src/emu/cpu/ssp1601/ssp1601.c b/src/emu/cpu/ssp1601/ssp1601.c new file mode 100644 index 00000000000..f3dee945d7c --- /dev/null +++ b/src/emu/cpu/ssp1601/ssp1601.c @@ -0,0 +1,918 @@ +/* + * Samsung SSP1601 DSP emulator + * + * Copyright 2008, Grazvydas Ignotas + * + * This code is released under the MAME license. + * + * + * notes: + * not everything is implemented, but it is accurate enough to + * properly emulate Virtua Racing for Genesis/MegaDrive: + * + * only Z and N status flags are emulated (others unused by VR) + * so all condition checks except N and Z are ignored (not used by VR) + * modifiers for 'OP a, ri' and ((ri)) are ignored (not used by VR) + * loop repeat mode when destination is (ri) is ignored + * ops not used by VR are not implemented + */ + +#include "debugger.h" +#include "deprecat.h" +#include "ssp1601.h" + + +/* detect ops with unimplemented/invalid fields. + * Useful for homebrew or if a new VR revision pops up. */ +//#define DO_CHECKS + + +typedef struct +{ + PAIR gr[8]; /* general regs, some are 16bit, some 32bit */ + union { + unsigned char r[8]; /* pointer registers, 4 for earch bank */ + struct { + unsigned char r0[4]; + unsigned char r1[4]; + }; + }; + union { + unsigned short RAM[256*2]; /* 2 256-word internal RAM banks */ + struct { + unsigned short RAM0[256]; + unsigned short RAM1[256]; + }; + }; + UINT16 stack[6]; /* 6-level hardware stack */ + PAIR ppc; +} +ssp1601_regs; + +static ssp1601_regs ssp1601; +static int g_cycles; + + +// 0 +#define rX ssp1601.gr[SSP_X].w.h +#define rY ssp1601.gr[SSP_Y].w.h +#define rA ssp1601.gr[SSP_A].w.h +#define rST ssp1601.gr[SSP_ST].w.h // 4 +#define rSTACK ssp1601.gr[SSP_STACK].w.h +#define rPC ssp1601.gr[SSP_PC].w.h +#define rP ssp1601.gr[SSP_P] + +#define rAL ssp1601.gr[SSP_A].w.l +#define rA32 ssp1601.gr[SSP_A].d +#define rIJ ssp1601.r + +#define IJind (((op>>6)&4)|(op&3)) + +#define PPC ssp1601.ppc.w.h + +#define FETCH() cpu_readop16(rPC++ << 1) +#define PROGRAM_WORD(a) program_read_word((a) << 1) +#define GET_PPC_OFFS() PPC +#define CHANGEPC() change_pc(rPC << 1) + +#define REG_READ(r) (((r) <= 4) ? ssp1601.gr[r].w.h : reg_read_handlers[r](r)) +#define REG_WRITE(r,d) { \ + int r1 = r; \ + if (r1 >= 4) reg_write_handlers[r1](r1,d); \ + else if (r1 > 0) ssp1601.gr[r1].w.h = d; \ +} + +// flags +#define SSP_FLAG_L (1<<0xc) +#define SSP_FLAG_Z (1<<0xd) +#define SSP_FLAG_V (1<<0xe) +#define SSP_FLAG_N (1<<0xf) + +// update ZN according to 32bit ACC. +#define UPD_ACC_ZN \ + rST &= ~(SSP_FLAG_Z|SSP_FLAG_N); \ + if (!rA32) rST |= SSP_FLAG_Z; \ + else rST |= (rA32>>16)&SSP_FLAG_N; + +// it seems SVP code never checks for L and OV, so we leave them out. +#define UPD_LZVN \ + rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ + if (!rA32) rST |= SSP_FLAG_Z; \ + else rST |= (rA32>>16)&SSP_FLAG_N; + +// standard cond processing. +// again, only Z and N is checked, as VR doesn't seem to use any other conds. +#define COND_CHECK \ + switch (op&0xf0) { \ + case 0x00: cond = 1; break; /* always true */ \ + case 0x50: cond = !((rST ^ (op<<5)) & SSP_FLAG_Z); break; /* Z matches f(?) bit */ \ + case 0x70: cond = !((rST ^ (op<<7)) & SSP_FLAG_N); break; /* N matches f(?) bit */ \ + default:logerror(__FILE__ " FIXME: unimplemented cond @ %04x\n", GET_PPC_OFFS()); break; \ + } + +// ops with accumulator. +// note that 'ld A' doesn't affect flags +#define OP_LDA(x) \ + rA = x + +#define OP_LDA32(x) \ + rA32 = x + +#define OP_SUBA(x) { \ + rA32 -= (x) << 16; \ + UPD_LZVN \ +} + +#define OP_SUBA32(x) { \ + rA32 -= (x); \ + UPD_LZVN \ +} + +#define OP_CMPA(x) { \ + UINT32 t = rA32 - ((x) << 16); \ + rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ + if (!t) rST |= SSP_FLAG_Z; \ + else rST |= (t>>16)&SSP_FLAG_N; \ +} + +#define OP_CMPA32(x) { \ + UINT32 t = rA32 - (x); \ + rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ + if (!t) rST |= SSP_FLAG_Z; \ + else rST |= (t>>16)&SSP_FLAG_N; \ +} + +#define OP_ADDA(x) { \ + rA32 += (x) << 16; \ + UPD_LZVN \ +} + +#define OP_ADDA32(x) { \ + rA32 += (x); \ + UPD_LZVN \ +} + +#define OP_ANDA(x) \ + rA32 &= (x) << 16; \ + UPD_ACC_ZN + +#define OP_ANDA32(x) \ + rA32 &= (x); \ + UPD_ACC_ZN + +#define OP_ORA(x) \ + rA32 |= (x) << 16; \ + UPD_ACC_ZN + +#define OP_ORA32(x) \ + rA32 |= (x); \ + UPD_ACC_ZN + +#define OP_EORA(x) \ + rA32 ^= (x) << 16; \ + UPD_ACC_ZN + +#define OP_EORA32(x) \ + rA32 ^= (x); \ + UPD_ACC_ZN + + +#define OP_CHECK32(OP) { \ + if ((op & 0x0f) == SSP_P) { /* A <- P */ \ + update_P(); \ + OP(rP.d); \ + break; \ + } \ + if ((op & 0x0f) == SSP_A) { /* A <- A */ \ + OP(rA32); \ + break; \ + } \ +} + + +#ifdef DO_CHECKS +#define CHECK_IMM16() if (op&0x1ff) logerror(__FILE__ " imm bits! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_B_SET() if (op&0x100) logerror(__FILE__ " b set! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_B_CLEAR() if (!(op&0x100)) logerror(__FILE__ " b clear! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_MOD() if (op&0x00c) logerror(__FILE__ " mod bits! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_10f() if (op&0x10f) logerror(__FILE__ " bits 10f! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_008() if (op&0x008) logerror(__FILE__ " bits 008! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_00f() if (op&0x00f) logerror(__FILE__ " bits 00f! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_0f0() if (op&0x0f0) logerror(__FILE__ " bits 0f0! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_1f0() if (op&0x1f0) logerror(__FILE__ " bits 1f0! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_RPL() if (rST&7) logerror(__FILE__ " unhandled RPL! %04x @ %04x\n", op, GET_PPC_OFFS()) +#define CHECK_ST(d) if((rST^d)&0xf98)logerror(__FILE__ " ssp FIXME ST %04x -> %04x @ %04x\n", rST, d, GET_PPC_OFFS()) +#else +#define CHECK_IMM16() +#define CHECK_B_SET() +#define CHECK_B_CLEAR() +#define CHECK_MOD() +#define CHECK_10f() +#define CHECK_008() +#define CHECK_00f() +#define CHECK_0f0() +#define CHECK_1f0() +#define CHECK_RPL() +#define CHECK_ST(d) +#endif + +#define CHIP_NAME "SSP1601" + +// ----------------------------------------------------- +// register i/o handlers + +static void update_P(void) +{ + int m1 = (signed short)rX; + int m2 = (signed short)rY; + rP.d = (m1 * m2 * 2); +} + +static UINT32 read_unknown(int reg) +{ + logerror("%s:%i FIXME\n", __FILE__, __LINE__); + return 0; +} + +static void write_unknown(int reg, UINT32 d) +{ + logerror("%s:%i FIXME\n", __FILE__, __LINE__); +} + +/* map EXT regs to virtual I/O range of 0x00-0x0f */ +static UINT32 read_ext(int reg) +{ + reg &= 7; + return io_read_word_16be((reg << 1)); +} + +static void write_ext(int reg, UINT32 d) +{ + reg &= 7; + io_write_word_16be((reg << 1), d); +} + +// 4 +static void write_ST(int reg, UINT32 d) +{ + CHECK_ST(d); + rST = d; +} + +// 5 +static UINT32 read_STACK(int reg) +{ + --rSTACK; + if ((signed short)rSTACK < 0) { + rSTACK = 5; + logerror(__FILE__ " FIXME: stack underflow! (%i) @ %04x\n", rSTACK, GET_PPC_OFFS()); + } + return ssp1601.stack[rSTACK]; +} + +static void write_STACK(int reg, UINT32 d) +{ + if (rSTACK >= 6) { + logerror(__FILE__ " FIXME: stack overflow! (%i) @ %04x\n", rSTACK, GET_PPC_OFFS()); + rSTACK = 0; + } + ssp1601.stack[rSTACK++] = d; +} + +// 6 +static UINT32 read_PC(int reg) +{ + return rPC; +} + +static void write_PC(int reg, UINT32 d) +{ + rPC = d; + g_cycles--; + CHANGEPC(); +} + +// 7 +static UINT32 read_P(int reg) +{ + update_P(); + return rP.w.h; +} + +// 15 +static UINT32 read_AL(int reg) +{ + /* apparently reading AL causes some effect on EXT bus, VR depends on that.. */ + read_ext(reg); + return rAL; +} + +static void write_AL(int reg, UINT32 d) +{ + write_ext(reg, d); + rAL = d; +} + + +typedef UINT32 (*read_func_t)(int reg); +typedef void (*write_func_t)(int reg, UINT32 d); + +static read_func_t reg_read_handlers[16] = +{ + read_unknown, read_unknown, read_unknown, read_unknown, // -, X, Y, A + read_unknown, // 4 ST + read_STACK, + read_PC, + read_P, + read_ext, // 8 + read_ext, + read_ext, + read_ext, + read_ext, // 12 + read_ext, + read_ext, + read_AL +}; + +static write_func_t reg_write_handlers[16] = +{ + write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A + write_ST, + write_STACK, + write_PC, + write_unknown, // 7 P (not writable) + write_ext, // 8 + write_ext, + write_ext, + write_ext, + write_ext, // 12 + write_ext, + write_ext, + write_AL +}; + +// ----------------------------------------------------- +// pointer register handlers + +// +#define ptr1_read(op) ptr1_read_(op&3,(op>>6)&4,(op<<1)&0x18) + +static UINT32 ptr1_read_(int ri, int isj2, int modi3) +{ + //int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); + UINT32 mask, add = 0, t = ri | isj2 | modi3; + unsigned char *rp = NULL; + switch (t) + { + // mod=0 (00) + case 0x00: + case 0x01: + case 0x02: return ssp1601.RAM0[ssp1601.r0[t&3]]; + case 0x03: return ssp1601.RAM0[0]; + case 0x04: + case 0x05: + case 0x06: return ssp1601.RAM1[ssp1601.r1[t&3]]; + case 0x07: return ssp1601.RAM1[0]; + // mod=1 (01), "+!" + case 0x08: + case 0x09: + case 0x0a: return ssp1601.RAM0[ssp1601.r0[t&3]++]; + case 0x0b: return ssp1601.RAM0[1]; + case 0x0c: + case 0x0d: + case 0x0e: return ssp1601.RAM1[ssp1601.r1[t&3]++]; + case 0x0f: return ssp1601.RAM1[1]; + // mod=2 (10), "-" + case 0x10: + case 0x11: + case 0x12: rp = &ssp1601.r0[t&3]; t = ssp1601.RAM0[*rp]; + if (!(rST&7)) { (*rp)--; return t; } + add = -1; goto modulo; + case 0x13: return ssp1601.RAM0[2]; + case 0x14: + case 0x15: + case 0x16: rp = &ssp1601.r1[t&3]; t = ssp1601.RAM1[*rp]; + if (!(rST&7)) { (*rp)--; return t; } + add = -1; goto modulo; + case 0x17: return ssp1601.RAM1[2]; + // mod=3 (11), "+" + case 0x18: + case 0x19: + case 0x1a: rp = &ssp1601.r0[t&3]; t = ssp1601.RAM0[*rp]; + if (!(rST&7)) { (*rp)++; return t; } + add = 1; goto modulo; + case 0x1b: return ssp1601.RAM0[3]; + case 0x1c: + case 0x1d: + case 0x1e: rp = &ssp1601.r1[t&3]; t = ssp1601.RAM1[*rp]; + if (!(rST&7)) { (*rp)++; return t; } + add = 1; goto modulo; + case 0x1f: return ssp1601.RAM1[3]; + } + + return 0; + +modulo: + mask = (1 << (rST&7)) - 1; + *rp = (*rp & ~mask) | ((*rp + add) & mask); + return t; +} + +static void ptr1_write(int op, UINT32 d) +{ + int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); + switch (t) + { + // mod=0 (00) + case 0x00: + case 0x01: + case 0x02: ssp1601.RAM0[ssp1601.r0[t&3]] = d; return; + case 0x03: ssp1601.RAM0[0] = d; return; + case 0x04: + case 0x05: + case 0x06: ssp1601.RAM1[ssp1601.r1[t&3]] = d; return; + case 0x07: ssp1601.RAM1[0] = d; return; + // mod=1 (01), "+!" + // mod=3, "+" + case 0x08: + case 0x09: + case 0x0a: ssp1601.RAM0[ssp1601.r0[t&3]++] = d; return; + case 0x0b: ssp1601.RAM0[1] = d; return; + case 0x0c: + case 0x0d: + case 0x0e: ssp1601.RAM1[ssp1601.r1[t&3]++] = d; return; + case 0x0f: ssp1601.RAM1[1] = d; return; + // mod=2 (10), "-" + case 0x10: + case 0x11: + case 0x12: ssp1601.RAM0[ssp1601.r0[t&3]--] = d; CHECK_RPL(); return; + case 0x13: ssp1601.RAM0[2] = d; return; + case 0x14: + case 0x15: + case 0x16: ssp1601.RAM1[ssp1601.r1[t&3]--] = d; CHECK_RPL(); return; + case 0x17: ssp1601.RAM1[2] = d; return; + // mod=3 (11), "+" + case 0x18: + case 0x19: + case 0x1a: ssp1601.RAM0[ssp1601.r0[t&3]++] = d; CHECK_RPL(); return; + case 0x1b: ssp1601.RAM0[3] = d; return; + case 0x1c: + case 0x1d: + case 0x1e: ssp1601.RAM1[ssp1601.r1[t&3]++] = d; CHECK_RPL(); return; + case 0x1f: ssp1601.RAM1[3] = d; return; + } +} + +static UINT32 ptr2_read(int op) +{ + int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); + switch (t) + { + // mod=0 (00) + case 0x00: + case 0x01: + case 0x02: mv = ssp1601.RAM0[ssp1601.r0[t&3]]++; break; + case 0x03: mv = ssp1601.RAM0[0]++; break; + case 0x04: + case 0x05: + case 0x06: mv = ssp1601.RAM1[ssp1601.r1[t&3]]++; break; + case 0x07: mv = ssp1601.RAM1[0]++; break; + // mod=1 (01) + case 0x0b: mv = ssp1601.RAM0[1]++; break; + case 0x0f: mv = ssp1601.RAM1[1]++; break; + // mod=2 (10) + case 0x13: mv = ssp1601.RAM0[2]++; break; + case 0x17: mv = ssp1601.RAM1[2]++; break; + // mod=3 (11) + case 0x1b: mv = ssp1601.RAM0[3]++; break; + case 0x1f: mv = ssp1601.RAM1[3]++; break; + default: logerror(__FILE__ " FIXME: unimplemented mod in ((rX)) @ %04x\n", GET_PPC_OFFS()); + return 0; + } + + return PROGRAM_WORD(mv); +} + + +// ----------------------------------------------------- + + +static void ssp1601_init(int index, int clock, const void *config, int (*irqcallback)(int)) +{ + state_save_register_item(CHIP_NAME, index, rX); + state_save_register_item(CHIP_NAME, index, rY); + state_save_register_item(CHIP_NAME, index, rA32); + state_save_register_item(CHIP_NAME, index, rST); + state_save_register_item(CHIP_NAME, index, rSTACK); + state_save_register_item(CHIP_NAME, index, rPC); + state_save_register_item(CHIP_NAME, index, rP.d); + state_save_register_item(CHIP_NAME, index, PPC); + state_save_register_item_array(CHIP_NAME, index, ssp1601.stack); + state_save_register_item_array(CHIP_NAME, index, ssp1601.r); + state_save_register_item_array(CHIP_NAME, index, ssp1601.RAM); + + /* clear the state */ + memset(&ssp1601, 0, sizeof(ssp1601)); + ssp1601.gr[0].w.h = 0xffff; // constant reg +} + +static void ssp1601_exit(void) +{ + /* nothing to do */ +} + +static void ssp1601_reset(void) +{ + rPC = 0x400; + rSTACK = 0; // ? using ascending stack + rST = 0; +} + + +static int ssp1601_execute(int cycles) +{ + g_cycles = cycles; + + while (g_cycles > 0) + { + int op; + UINT32 tmpv; + + PPC = rPC; + + CALL_DEBUGGER(rPC); + + op = FETCH(); + + switch (op >> 9) + { + // ld d, s + case 0x00: + CHECK_B_SET(); + if (op == 0) break; // nop + if (op == ((SSP_A<<4)|SSP_P)) { // A <- P + update_P(); + rA32 = rP.d; + } + else + { + tmpv = REG_READ(op & 0x0f); + REG_WRITE((op & 0xf0) >> 4, tmpv); + } + break; + + // ld d, (ri) + case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break; + + // ld (ri), s + case 0x02: tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv); break; + + // ldi d, imm + case 0x04: CHECK_10f(); tmpv = FETCH(); REG_WRITE((op & 0xf0) >> 4, tmpv); g_cycles--; break; + + // ld d, ((ri)) + case 0x05: CHECK_MOD(); tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); g_cycles -= 2; break; + + // ldi (ri), imm + case 0x06: tmpv = FETCH(); ptr1_write(op, tmpv); g_cycles--; break; + + // ld adr, a + case 0x07: ssp1601.RAM[op & 0x1ff] = rA; break; + + // ld d, ri + case 0x09: CHECK_MOD(); tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv); break; + + // ld ri, s + case 0x0a: CHECK_MOD(); rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4); break; + + // ldi ri, simm + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: rIJ[(op>>8)&7] = op; break; + + // call cond, addr + case 0x24: { + int cond = 0; + CHECK_00f(); + COND_CHECK + if (cond) { int new_PC = FETCH(); write_STACK(SSP_STACK, rPC); rPC = new_PC; CHANGEPC(); } + else rPC++; + g_cycles--; // always 2 cycles + break; + } + + // ld d, (a) + case 0x25: + CHECK_10f(); + tmpv = PROGRAM_WORD(rA); + REG_WRITE((op & 0xf0) >> 4, tmpv); + g_cycles -= 2; // 3 cycles total + break; + + // bra cond, addr + case 0x26: { + int cond = 0; + CHECK_00f(); + COND_CHECK + if (cond) { rPC = FETCH(); CHANGEPC(); } + else rPC++; + g_cycles--; + break; + } + + // mod cond, op + case 0x48: { + int cond = 0; + CHECK_008(); + COND_CHECK + if (cond) { + switch (op & 7) { + case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic) + case 3: rA32 <<= 1; break; // shl + case 6: rA32 = -(signed int)rA32; break; // neg + case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs + default: logerror(__FILE__ " FIXME: unhandled mod %i @ %04x\n", + op&7, GET_PPC_OFFS()); + } + UPD_ACC_ZN + } + break; + } + + // mpys? + case 0x1b: + CHECK_B_CLEAR(); + update_P(); + rA32 -= rP.d; + UPD_ACC_ZN + rX = ptr1_read_(op&3, 0, (op<<1)&0x18); + rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); + break; + + // mpya (rj), (ri), b + case 0x4b: + CHECK_B_CLEAR(); + update_P(); + rA32 += rP.d; + UPD_ACC_ZN + rX = ptr1_read_(op&3, 0, (op<<1)&0x18); + rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); + break; + + // mld (rj), (ri), b + case 0x5b: + CHECK_B_CLEAR(); + rA32 = 0; + rST &= 0x0fff; + rST |= SSP_FLAG_Z; + rX = ptr1_read_(op&3, 0, (op<<1)&0x18); + rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); + break; + + // OP a, s + case 0x10: CHECK_1f0(); OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv); break; + case 0x30: CHECK_1f0(); OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv); break; + case 0x40: CHECK_1f0(); OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv); break; + case 0x50: CHECK_1f0(); OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv); break; + case 0x60: CHECK_1f0(); OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv); break; + case 0x70: CHECK_1f0(); OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv); break; + + // OP a, (ri) + case 0x11: CHECK_0f0(); tmpv = ptr1_read(op); OP_SUBA(tmpv); break; + case 0x31: CHECK_0f0(); tmpv = ptr1_read(op); OP_CMPA(tmpv); break; + case 0x41: CHECK_0f0(); tmpv = ptr1_read(op); OP_ADDA(tmpv); break; + case 0x51: CHECK_0f0(); tmpv = ptr1_read(op); OP_ANDA(tmpv); break; + case 0x61: CHECK_0f0(); tmpv = ptr1_read(op); OP_ORA (tmpv); break; + case 0x71: CHECK_0f0(); tmpv = ptr1_read(op); OP_EORA(tmpv); break; + + // OP a, adr + case 0x03: tmpv = ssp1601.RAM[op & 0x1ff]; OP_LDA (tmpv); break; + case 0x13: tmpv = ssp1601.RAM[op & 0x1ff]; OP_SUBA(tmpv); break; + case 0x33: tmpv = ssp1601.RAM[op & 0x1ff]; OP_CMPA(tmpv); break; + case 0x43: tmpv = ssp1601.RAM[op & 0x1ff]; OP_ADDA(tmpv); break; + case 0x53: tmpv = ssp1601.RAM[op & 0x1ff]; OP_ANDA(tmpv); break; + case 0x63: tmpv = ssp1601.RAM[op & 0x1ff]; OP_ORA (tmpv); break; + case 0x73: tmpv = ssp1601.RAM[op & 0x1ff]; OP_EORA(tmpv); break; + + // OP a, imm + case 0x14: CHECK_IMM16(); tmpv = FETCH(); OP_SUBA(tmpv); g_cycles--; break; + case 0x34: CHECK_IMM16(); tmpv = FETCH(); OP_CMPA(tmpv); g_cycles--; break; + case 0x44: CHECK_IMM16(); tmpv = FETCH(); OP_ADDA(tmpv); g_cycles--; break; + case 0x54: CHECK_IMM16(); tmpv = FETCH(); OP_ANDA(tmpv); g_cycles--; break; + case 0x64: CHECK_IMM16(); tmpv = FETCH(); OP_ORA (tmpv); g_cycles--; break; + case 0x74: CHECK_IMM16(); tmpv = FETCH(); OP_EORA(tmpv); g_cycles--; break; + + // OP a, ((ri)) + case 0x15: CHECK_MOD(); tmpv = ptr2_read(op); OP_SUBA(tmpv); g_cycles -= 2; break; + case 0x35: CHECK_MOD(); tmpv = ptr2_read(op); OP_CMPA(tmpv); g_cycles -= 2; break; + case 0x45: CHECK_MOD(); tmpv = ptr2_read(op); OP_ADDA(tmpv); g_cycles -= 2; break; + case 0x55: CHECK_MOD(); tmpv = ptr2_read(op); OP_ANDA(tmpv); g_cycles -= 2; break; + case 0x65: CHECK_MOD(); tmpv = ptr2_read(op); OP_ORA (tmpv); g_cycles -= 2; break; + case 0x75: CHECK_MOD(); tmpv = ptr2_read(op); OP_EORA(tmpv); g_cycles -= 2; break; + + // OP a, ri + case 0x19: CHECK_MOD(); tmpv = rIJ[IJind]; OP_SUBA(tmpv); break; + case 0x39: CHECK_MOD(); tmpv = rIJ[IJind]; OP_CMPA(tmpv); break; + case 0x49: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ADDA(tmpv); break; + case 0x59: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ANDA(tmpv); break; + case 0x69: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ORA (tmpv); break; + case 0x79: CHECK_MOD(); tmpv = rIJ[IJind]; OP_EORA(tmpv); break; + + // OP simm + case 0x1c: CHECK_B_SET(); OP_SUBA(op & 0xff); break; + case 0x3c: CHECK_B_SET(); OP_CMPA(op & 0xff); break; + case 0x4c: CHECK_B_SET(); OP_ADDA(op & 0xff); break; + case 0x5c: CHECK_B_SET(); OP_ANDA(op & 0xff); break; + case 0x6c: CHECK_B_SET(); OP_ORA (op & 0xff); break; + case 0x7c: CHECK_B_SET(); OP_EORA(op & 0xff); break; + + default: + logerror(__FILE__ " FIXME unhandled op %04x @ %04x\n", op, GET_PPC_OFFS()); + break; + } + g_cycles--; + } + + update_P(); + return cycles - g_cycles; +} + + +/************************************************************************** + * MAME interface + **************************************************************************/ + +static void ssp1601_get_context(void *regs) +{ + /* copy the context */ + if (regs) + *(ssp1601_regs *)regs = ssp1601; +} + +static void ssp1601_set_context(void *regs) +{ + /* copy the context */ + if (regs) + ssp1601 = *(ssp1601_regs *)regs; +} + +#ifdef ENABLE_DEBUGGER +static offs_t ssp1601_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) +{ + return dasm_ssp1601(buffer, pc, oprom); +} +#endif /* ENABLE_DEBUGGER */ + +#if (HAS_SSP1601) + +static void ssp1601_set_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + + case CPUINFO_INT_REGISTER + SSP_X: rX = info->i; break; + case CPUINFO_INT_REGISTER + SSP_Y: rY = info->i; break; + case CPUINFO_INT_REGISTER + SSP_A: rA32 = info->i; break; + case CPUINFO_INT_REGISTER + SSP_ST: rST = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK: rSTACK = info->i; break; + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + SSP_PC: rPC = info->i; break; + case CPUINFO_INT_REGISTER + SSP_P: rP.d = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK0: ssp1601.stack[0] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK1: ssp1601.stack[1] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK2: ssp1601.stack[2] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK3: ssp1601.stack[3] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK4: ssp1601.stack[4] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_STACK5: ssp1601.stack[5] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR0: ssp1601.r[0] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR1: ssp1601.r[1] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR2: ssp1601.r[2] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR3: ssp1601.r[3] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR4: ssp1601.r[4] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR5: ssp1601.r[5] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR6: ssp1601.r[6] = info->i; break; + case CPUINFO_INT_REGISTER + SSP_PR7: ssp1601.r[7] = info->i; break; + +// case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; +// case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break; +// case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(2, info->i); break; + } +} + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +void ssp1601_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ssp1601); break; + case CPUINFO_INT_INPUT_LINES: info->i = 3; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; 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 = 2; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; + + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -1; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; + case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break; + case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 4; break; + case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; + + case CPUINFO_INT_INPUT_STATE + 0: /* not implemented */ break; + + case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break; + + case CPUINFO_INT_REGISTER + SSP_R0: info->i = ssp1601.gr[0].w.h; break; + case CPUINFO_INT_REGISTER + SSP_X: info->i = rX; break; + case CPUINFO_INT_REGISTER + SSP_Y: info->i = rY; break; + case CPUINFO_INT_REGISTER + SSP_A: info->i = rA32; break; + case CPUINFO_INT_REGISTER + SSP_ST: info->i = rST; break; + case CPUINFO_INT_REGISTER + SSP_STACK: info->i = rSTACK; break; + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + SSP_PC: info->i = rPC; break; + case CPUINFO_INT_REGISTER + SSP_P: info->i = rP.d; break; + case CPUINFO_INT_REGISTER + SSP_STACK0: info->i = ssp1601.stack[0]; break; + case CPUINFO_INT_REGISTER + SSP_STACK1: info->i = ssp1601.stack[1]; break; + case CPUINFO_INT_REGISTER + SSP_STACK2: info->i = ssp1601.stack[2]; break; + case CPUINFO_INT_REGISTER + SSP_STACK3: info->i = ssp1601.stack[3]; break; + case CPUINFO_INT_REGISTER + SSP_STACK4: info->i = ssp1601.stack[4]; break; + case CPUINFO_INT_REGISTER + SSP_STACK5: info->i = ssp1601.stack[5]; break; + case CPUINFO_INT_REGISTER + SSP_PR0: info->i = ssp1601.r[0]; break; + case CPUINFO_INT_REGISTER + SSP_PR1: info->i = ssp1601.r[1]; break; + case CPUINFO_INT_REGISTER + SSP_PR2: info->i = ssp1601.r[2]; break; + case CPUINFO_INT_REGISTER + SSP_PR3: info->i = ssp1601.r[3]; break; + case CPUINFO_INT_REGISTER + SSP_PR4: info->i = ssp1601.r[4]; break; + case CPUINFO_INT_REGISTER + SSP_PR5: info->i = ssp1601.r[5]; break; + case CPUINFO_INT_REGISTER + SSP_PR6: info->i = ssp1601.r[6]; break; + case CPUINFO_INT_REGISTER + SSP_PR7: info->i = ssp1601.r[7]; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_SET_INFO: info->setinfo = ssp1601_set_info; break; + case CPUINFO_PTR_GET_CONTEXT: info->getcontext = ssp1601_get_context; break; + case CPUINFO_PTR_SET_CONTEXT: info->setcontext = ssp1601_set_context; break; + case CPUINFO_PTR_INIT: info->init = ssp1601_init; break; + case CPUINFO_PTR_RESET: info->reset = ssp1601_reset; break; + case CPUINFO_PTR_EXIT: info->exit = ssp1601_exit; break; + case CPUINFO_PTR_EXECUTE: info->execute = ssp1601_execute; break; + case CPUINFO_PTR_BURN: info->burn = NULL; break; +#ifdef ENABLE_DEBUGGER + case CPUINFO_PTR_DISASSEMBLE: info->disassemble = ssp1601_dasm; break; +#endif /* ENABLE_DEBUGGER */ + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &g_cycles; break; + + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map16 = NULL; break; + case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map16 = NULL; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, CHIP_NAME); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "SSP1601 DSP"); break; + case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break; + case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; + case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Grazvydas Ignotas"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%c%c%c%c", (rST&SSP_FLAG_N)?'N':'.', (rST&SSP_FLAG_V)?'V':'.', + (rST&SSP_FLAG_Z)?'Z':'.', (rST&SSP_FLAG_L)?'L':'.'); + break; + + case CPUINFO_STR_REGISTER + SSP_R0: sprintf(info->s, "REG0 :%04X", ssp1601.gr[0].w.h); break; + case CPUINFO_STR_REGISTER + SSP_X: sprintf(info->s, "X :%04X", rX); break; + case CPUINFO_STR_REGISTER + SSP_Y: sprintf(info->s, "Y :%04X", rY); break; + case CPUINFO_STR_REGISTER + SSP_A: sprintf(info->s, "A :%08X", rA32); break; + case CPUINFO_STR_REGISTER + SSP_ST: sprintf(info->s, "ST :%04X", rST); break; + case CPUINFO_STR_REGISTER + SSP_STACK: sprintf(info->s, "STACK :%04X", rSTACK); break; + case CPUINFO_STR_REGISTER + SSP_PC: sprintf(info->s, "PC :%04X", rPC); break; + case CPUINFO_STR_REGISTER + SSP_P: sprintf(info->s, "P :%08X", rP.d); break; + case CPUINFO_STR_REGISTER + SSP_STACK0: sprintf(info->s, "STACK0 :%04X", ssp1601.stack[0]); break; + case CPUINFO_STR_REGISTER + SSP_STACK1: sprintf(info->s, "STACK1 :%04X", ssp1601.stack[1]); break; + case CPUINFO_STR_REGISTER + SSP_STACK2: sprintf(info->s, "STACK2 :%04X", ssp1601.stack[2]); break; + case CPUINFO_STR_REGISTER + SSP_STACK3: sprintf(info->s, "STACK3 :%04X", ssp1601.stack[3]); break; + case CPUINFO_STR_REGISTER + SSP_STACK4: sprintf(info->s, "STACK4 :%04X", ssp1601.stack[4]); break; + case CPUINFO_STR_REGISTER + SSP_STACK5: sprintf(info->s, "STACK5 :%04X", ssp1601.stack[5]); break; + case CPUINFO_STR_REGISTER + SSP_PR0: sprintf(info->s, "R0 :%02X", ssp1601.r[0]); break; + case CPUINFO_STR_REGISTER + SSP_PR1: sprintf(info->s, "R1 :%02X", ssp1601.r[1]); break; + case CPUINFO_STR_REGISTER + SSP_PR2: sprintf(info->s, "R2 :%02X", ssp1601.r[2]); break; + case CPUINFO_STR_REGISTER + SSP_PR3: sprintf(info->s, "R3 :%02X", ssp1601.r[3]); break; + case CPUINFO_STR_REGISTER + SSP_PR4: sprintf(info->s, "R4 :%02X", ssp1601.r[4]); break; + case CPUINFO_STR_REGISTER + SSP_PR5: sprintf(info->s, "R5 :%02X", ssp1601.r[5]); break; + case CPUINFO_STR_REGISTER + SSP_PR6: sprintf(info->s, "R6 :%02X", ssp1601.r[6]); break; + case CPUINFO_STR_REGISTER + SSP_PR7: sprintf(info->s, "R7 :%02X", ssp1601.r[7]); break; + } +} +#endif + +// vim:ts=4 + diff --git a/src/emu/cpu/ssp1601/ssp1601.h b/src/emu/cpu/ssp1601/ssp1601.h new file mode 100644 index 00000000000..3456e54700d --- /dev/null +++ b/src/emu/cpu/ssp1601/ssp1601.h @@ -0,0 +1,24 @@ +#ifndef SSP1601_H +#define SSP1601_H + +#include "cpuintrf.h" + +enum { + /* general registers */ + SSP_R0, SSP_X, SSP_Y, SSP_A, + SSP_ST, SSP_STACK, SSP_PC, SSP_P, + /* hardware stack */ + SSP_STACK0, SSP_STACK1, SSP_STACK2, SSP_STACK3, SSP_STACK4, SSP_STACK5, + /* pointer registers */ + SSP_PR0, SSP_PR1, SSP_PR2, SSP_PR3, SSP_PR4, SSP_PR5, SSP_PR6, SSP_PR7 +}; + +#if (HAS_SSP1601) +void ssp1601_get_info(UINT32 state, cpuinfo *info); +#endif + +#ifdef ENABLE_DEBUGGER +extern unsigned dasm_ssp1601(char *buffer, unsigned pc, const UINT8 *oprom); +#endif + +#endif /* SSP1601_H */ diff --git a/src/emu/cpu/ssp1601/ssp1601d.c b/src/emu/cpu/ssp1601/ssp1601d.c new file mode 100644 index 00000000000..61a15662606 --- /dev/null +++ b/src/emu/cpu/ssp1601/ssp1601d.c @@ -0,0 +1,290 @@ +/* + + SSP1601 disassembler + written by Pierpaolo Prazzoli + updated for SSP1601 by Grazvydas Ignotas + +*/ + +#include +#include "debugger.h" +#include "cpuintrf.h" + + +static const char *const reg[16] = +{ + "-", "X", "Y", "A", + "ST", "STACK", "PC", "P", + "EXT0", "EXT1", "EXT2", "EXT3", + "EXT4", "EXT5", "EXT6", "AL" +}; + +static const char *const rij[8] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" +}; + +static const char *const modifier[4] = +{ + "", "+!", "-", "+" +}; + +static const char *const modifier_sf[4] = +{ + "|00", "|01", "|10", "|11" +}; + +static const char *const cond[16] = +{ + "always", "RESERVED", "gpi0", "gpi1", + "l", "z", "ov", "n", + "diof", "gpi2", "gpi3", "RESERVED", + "RESERVED", "RESERVED", "RESERVED", "RESERVED", +}; + +static const char *const acc_op[8] = +{ + "ror", "rol", "shr", "shl", "inc", "dec", "neg", "abs" +}; + +// pag. 81 uses different addresses! +static const char *const flag_op[16] = +{ + "?", "?", "resl", "setl", "resie", "setie", "?", "?", "resop", "setop", "?", "?", "?", "?", "res", "set" +}; + +static const char *const arith_ops[8] = +{ + "", "add", "", "cmp", "add", "and", "or", "eor" +}; + + +#define BIT_B ((op >> 8) & 1) +#define RIJ rij[(BIT_B << 2) + (op & 3)] +#define RI(i) rij[(i) & 3] +#define RJ(i) rij[((i) & 3) + 4] +#define MODIFIER(mod,r3) (((r3) == 3) ? modifier_sf[mod] : modifier[mod]) +#define MODIFIER_LOW MODIFIER((op >> 2) & 3, op&3) +#define MODIFIER_HIGH MODIFIER((op >> 6) & 3, (op >> 4)&3) + +#define READ_OP_DASM(p) ((base_oprom[p] << 8) | base_oprom[(p) + 1]) + +static char *get_cond(int op) +{ + static char scond[16]; + if (op&0xf0) sprintf(scond, "%s=%i", cond[(op >> 4) & 0xf], BIT_B); + else sprintf(scond, "%s", cond[(op >> 4) & 0xf]); + return scond; +} + + +unsigned dasm_ssp1601(char *buffer, unsigned pc, const UINT8 *oprom) +{ + const UINT8 *base_oprom; + UINT16 op; + int size = 1; + int flags = 0; + + base_oprom = oprom; + + op = READ_OP_DASM(0); + + switch (op >> 9) + { + case 0x00: + if(op == 0) + { + // nop + sprintf(buffer, "nop"); + } + else if((op & 0xff) == 0x65) + { + // ret + sprintf(buffer, "ret"); + flags |= DASMFLAG_STEP_OUT; + } + else + { + // ld d, s + sprintf(buffer, "ld %s, %s", reg[(op >> 4) & 0xf], reg[op & 0xf]); + } + break; + + // ld d, (ri) + case 0x01: + sprintf(buffer, "ld %s, (%s%s)", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW); + break; + + // ld (ri), s + case 0x02: + sprintf(buffer, "ld (%s%s), %s", RIJ, MODIFIER_LOW, reg[(op >> 4) & 0xf]); + break; + + // ld a, addr + case 0x03: + sprintf(buffer, "ld A, %X", op & 0x1ff); + break; + + // ldi d, imm + case 0x04: + sprintf(buffer, "ld %s, %X", reg[(op >> 4) & 0xf], READ_OP_DASM(2)); + size = 2; + break; + + // ld d, ((ri)) + case 0x05: + sprintf(buffer, "ld %s, ((%s%s))", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW); + break; + + // ldi (ri), imm + case 0x06: + sprintf(buffer, "ld (%s%s), %X", RIJ, MODIFIER_LOW, READ_OP_DASM(2)); + size = 2; + break; + + // ld addr, a + case 0x07: + sprintf(buffer, "ld %X, A", op & 0x1ff); + break; + + // ld d, ri + case 0x09: + sprintf(buffer, "ld %s, %s%s", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW); + break; + + // ld ri, s + case 0x0a: + sprintf(buffer, "ld %s%s, %s", RIJ, MODIFIER_LOW, reg[(op >> 4) & 0xf]); + break; + + // ldi ri, simm + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + sprintf(buffer, "ldi %s, %X", rij[(op >> 8) & 7], op & 0xff); + break; + + // op a, s + case 0x10: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + sprintf(buffer, "%s A, %s", arith_ops[op >> 13], reg[op & 0xf]); + break; + + // op a, (ri) + case 0x11: + case 0x31: + case 0x41: + case 0x51: + case 0x61: + case 0x71: + sprintf(buffer, "%s A, (%s%s)", arith_ops[op >> 13], RIJ, MODIFIER_LOW); + break; + + // op a, adr + case 0x13: + case 0x33: + case 0x43: + case 0x53: + case 0x63: + case 0x73: + sprintf(buffer, "%s A, %X", arith_ops[op >> 13], op & 0x1ff); + break; + + // subi a, imm + case 0x14: + case 0x34: + case 0x44: + case 0x54: + case 0x64: + case 0x74: + sprintf(buffer, "%si A, %X", arith_ops[op >> 13], READ_OP_DASM(2)); + size = 2; + break; + + // op a, ((ri)) + case 0x15: + case 0x35: + case 0x45: + case 0x55: + case 0x65: + case 0x75: + sprintf(buffer, "%s A, ((%s%s))", arith_ops[op >> 13], RIJ, MODIFIER_LOW); + break; + + // sub a, ri + case 0x19: + case 0x39: + case 0x49: + case 0x59: + case 0x69: + case 0x79: + sprintf(buffer, "%s A, %s%s", arith_ops[op >> 13], RIJ, MODIFIER_LOW); + break; + + // mpys (rj), (ri), b + case 0x1b: + sprintf(buffer, "mpya (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B); + break; + + // subi simm + case 0x1c: + case 0x3c: + case 0x4c: + case 0x5c: + case 0x6c: + case 0x7c: + sprintf(buffer, "%si %X", arith_ops[op >> 13], op & 0xff); + break; + + // call cond, addr + case 0x24: + sprintf(buffer, "call %s, %X", get_cond(op), READ_OP_DASM(2)); + flags |= DASMFLAG_STEP_OVER; + size = 2; + break; + + // ld d, (a) + case 0x25: + sprintf(buffer, "ld %s, (A)", reg[(op >> 4) & 0xf]); + break; + + // bra cond, addr + case 0x26: + sprintf(buffer, "bra %s, %X", get_cond(op), READ_OP_DASM(2)); + size = 2; + break; + + // mod cond, op + case 0x48: + sprintf(buffer, "mod %s, %s", get_cond(op), acc_op[op & 7]); + break; + + // mod f, op + case 0x4a: + sprintf(buffer, "%s", flag_op[op & 0xf]); + break; + + // mpya (rj), (ri), b + case 0x4b: + sprintf(buffer, "mpya (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B); + break; + + // mld (rj), (ri), b + case 0x5b: + sprintf(buffer, "mld (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B); + break; + + default: + sprintf(buffer, "OP = %04X", op); + break; + } + + return size | flags | DASMFLAG_SUPPORTED; +} + +// vim:ts=4 diff --git a/src/emu/cpu/ssp1610/ssp1610.c b/src/emu/cpu/ssp1610/ssp1610.c deleted file mode 100644 index 5c5486efff3..00000000000 --- a/src/emu/cpu/ssp1610/ssp1610.c +++ /dev/null @@ -1,870 +0,0 @@ -/******************************************************************** - SSP1610 cpu emulator - written by Pierpaolo Prazzoli - - Very very preliminary. Still working on it... - -*********************************************************************/ - -#include "debugger.h" -#include "deprecat.h" -#include "ssp1610.h" - -#define READ_OP(addr) (cpu_readop16(addr<<1)) - -static int ssp1610_ICount; - -/* Registers */ - -enum -{ - SSP1610_REG0 = 1, SSP1610_X, SSP1610_Y, SSP1610_A, SSP1610_ST, SSP1610_STACK, SSP1610_PC, - SSP1610_P, SSP1610_AL, SSP1610_XST, SSP1610_PL, SSP1610_SRCR, SSP1610_BRCR, SSP1610_BRER, - SSP1610_XRD0, SSP1610_XRD1, SSP1610_AE, SSP1610_DIOR, SSP1610_GR22, SSP1610_GR23, - SSP1610_EXT0, SSP1610_EXT1, SSP1610_EXT2, SSP1610_EXT3, SSP1610_EXT4, SSP1610_EXT5, SSP1610_EXT6, SSP1610_EXT7 -}; - -/* Internal registers */ -typedef struct -{ - UINT32 regs[32]; // some are 8bits, some 16bits and some 32bits - - UINT16 ppc; - -} ssp1610_regs; - -static ssp1610_regs ssp1610; - -// number of bits of each register -static const UINT8 regs_width[] = -{ - 16, 16, 16, 32, 16, 16, 16, 32, 16, 0, 0, 16, 16, 0, 0, 8, - 8, 16, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 -}; - -// REGISTERS - -#define PPC ssp1610.ppc - -#define REG0 ssp1610.regs[0] -#define X ssp1610.regs[1] -#define Y ssp1610.regs[2] -#define A ssp1610.regs[3] -#define ST ssp1610.regs[4] -//swapped stack and pc (docs wrong...) -#define STACK ssp1610.regs[5] -#define PC ssp1610.regs[6] -#define P ssp1610.regs[7] -#define AL ssp1610.regs[8] -// 9 -// 10 -#define XST ssp1610.regs[11] -#define PL ssp1610.regs[12] -// 13 -// 14 -#define SRCR ssp1610.regs[15] -#define BRCR ssp1610.regs[16] -#define BRER ssp1610.regs[17] -#define XRD0 ssp1610.regs[18] -#define XRD1 ssp1610.regs[19] -#define AE ssp1610.regs[20] -#define DIOR ssp1610.regs[21] -#define GR22 ssp1610.regs[22] -#define GR23 ssp1610.regs[23] -#define EXT0 ssp1610.regs[24] -#define EXT1 ssp1610.regs[25] -#define EXT2 ssp1610.regs[26] -#define EXT3 ssp1610.regs[27] -#define EXT4 ssp1610.regs[28] -#define EXT5 ssp1610.regs[29] -#define EXT6 ssp1610.regs[30] -#define EXT7 ssp1610.regs[31] - -// CONDITIONS - -#define IS_PC 6 - -// CONTROL bits - - -#define RPL ((ST >> 0) & 7) -#define RB ((ST >> 3) & 3) -#define GP0_0 ((ST >> 5) & 1) -#define GP0_1 ((ST >> 6) & 1) -#define IE ((ST >> 7) & 1) -#define OP ((ST >> 8) & 1) -#define MACS ((ST >> 9) & 1) - - -// FLAG bits - - -#define GPI_0 ((ST >> 10) & 1) -#define GPI_1 ((ST >> 11) & 1) - - -#define L ((ST >> 12) & 1) -#define Z ((ST >> 13) & 1) -#define OV ((ST >> 14) & 1) -#define N ((ST >> 15) & 1) - -#define SET_L(value) ST = (ST & ~(1 << 12)) | ((value) << 12) -#define SET_Z(value) ST = (ST & ~(1 << 13)) | ((value) << 13) -#define SET_OV(value) ST = (ST & ~(1 << 14)) | ((value) << 14) -#define SET_N(value) ST = (ST & ~(1 << 15)) | ((value) << 15) - -#define SET_OVSUB(x,y,z)(ST = (ST & ~(1 << 14)) | ((((z) ^ (y)) & ((y) ^ (x)) & 0x80000000) ? (1 << 14): 0)) - -static void ssp1610_init(int index, int clock, const void *config, int (*irqcallback)(int)) -{ - REG0 = 0xffff; // read-only register -} - -static void ssp1610_reset(void) -{ - ST = 0; - - // latch it from 0 but it's selectable (hard-coded for now) - PC = 0x400; -} - -static void ssp1610_exit(void) -{ - // nothing to do -} - -static int ssp1610_execute(int cycles) -{ - ssp1610_ICount = cycles; - - do - { - UINT16 op; - - PPC = PC; /* copy PC to previous PC */ - - CALL_DEBUGGER(PC); - - op = READ_OP(PC); - - PC++; - - switch((op >> 9)) - { - case 0x00: - - if(op == 0) // right? - { - // nop - - } - else if((op & 0xff) == 0x65) - { - // ret - - } - else - { - // ld d, s - - int s = op & 0xf; - int d = (op >> 4) & 0xf; - - // TODO: handle special cases... and complete ALU operations - - if(regs_width[d] == 16 && (regs_width[s] == 16 || regs_width[s] == 8)) - { - ssp1610.regs[d] = ssp1610.regs[s]; - } - else if(regs_width[d] == 16 && regs_width[s] == 32) - { - ssp1610.regs[d] = (ssp1610.regs[s] >> 16); - } - else if(regs_width[d] == 32 && (regs_width[s] == 16 || regs_width[s] == 8)) - { - ssp1610.regs[d] = (ssp1610.regs[s] << 16) | (ssp1610.regs[d] & 0xffff); - } - else if(regs_width[d] == 32 && regs_width[s] == 32) - { - // wrong! if P is s then only the top 16bits are transferred - ssp1610.regs[d] = (ssp1610.regs[s] & 0xffff0000) | (ssp1610.regs[d] & 0xffff); - } - - if(d == IS_PC) // if d is PC one more cycle - { - ssp1610_ICount--; - change_pc(PC); - } - - } - - break; - - // ld d, (ri) -> probably right - case 0x01: // or ldi simm ? - - break; - - // ld (ri), s - case 0x02: - - break; - - // ld a, addr - case 0x03: - - break; - - // ldi d, imm - case 0x04: - - - break; - - // ld d, ((ri)) - case 0x05: - - break; - - // ldi (ri), imm - case 0x06: - - break; - - // ld addr, a -> almost sure it's this one. some of the 1st 4 bits are set in the code - case 0x07: // or ld d, (a) ? - - break; - - // ld d, ri - case 0x09: - - break; - - // ld ri, s - case 0x0a: - - break; - - // mpys (rj), (ri), b - case 0x0b: - - break; - - // ldi ri, simm - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - - - break; - - // sub a, s - case 0x10: - - break; - - // sub a, (ri) - case 0x11: - - break; - - // mpys s, (ri), b - case 0x12: - - break; - - // sub a, adr - case 0x13: - - break; - - // subi a, imm - case 0x14: - - break; - - // sub a, ((ri)) - case 0x15: - - break; - - // sub a, ri - case 0x19: - - break; - - // mset reg, (ri), s - case 0x1a: - case 0x1b: - - break; - - // subi simm - case 0x1c: - - break; - - // sub a, erij - case 0x23: - - break; - - // call cond, addr - case 0x24: //f bit? - - break; - - // bra cond, addr - case 0x26: //f bit? - { - UINT16 new_pc = READ_OP(PC); - UINT8 f = (op >> 8) & 1; - UINT8 cond = 0; - PC++; - - switch((op >> 4) & 0xf) - { - case 0x0: - case 0x1: - cond = f; // to jump always - break; - - case 0x2: - case 0x3: - // reserved - break; - - case 0x4: - cond = GPI_0 == 0; - break; - - case 0x5: - cond = GPI_0 == 1; - break; - - case 0x6: - cond = GPI_1 == 0; - break; - - case 0x7: - cond = GPI_1 == 1; - break; - - case 0x8: - cond = L == 0; - break; - - case 0x9: - cond = L == 1; - break; - - case 0xa: - cond = Z == 0; - break; - - case 0xb: - cond = Z == 1; - break; - - case 0xc: - cond = OV == 0; - break; - - case 0xd: - cond = OV == 1; - break; - - case 0xe: - cond = N == 0; - break; - - case 0xf: - cond = N == 1; - break; - } - - if((cond && f) || (!cond && !f)) - { - PPC = PC; - PC = new_pc; - change_pc(PC); - } - - ssp1610_ICount--; - } - - break; - - - case 0x28: - - if(op & 0x100) - { - // slow imm - - } - else - { - // stop - - } - - break; - - // cmp a, s - case 0x30: - - break; - - // cmp a, (ri) - case 0x31: - - break; - - // cmp a, adr - case 0x33: - - break; - - // cmpi a, imm - case 0x34: - { - UINT16 imm = READ_OP(PC) << 16; -#if 0 - UINT64 tmp = (UINT64)A - (UINT64)imm; -#else - // The previous line causes a bus error in Apple's GCC as of 10.4.9: - // i686-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5367) - // The gcc included with the Leopard Beta fixes this error. - // Using the volatile tempA works around the bus error. - volatile UINT32 tempA = A; - UINT64 tmp = (UINT64)tempA - (UINT64)imm; -#endif - PC++; - - // right flags? - - SET_L(A < imm); - SET_Z((A & 0xffff0000) == imm); - SET_N(((INT32) A) < ((INT32)imm)); - SET_OVSUB(imm,A,tmp); - - // A = saturated value - if(OP && OV) - { - if((INT64)tmp > 0x7fffff) - A = 0x7fffff; - else if((INT64)tmp < -0x800000) - A = 0x800000; - } - } - break; - - // cmp a, ((ri)) - case 0x35: - - break; - - // cmp a, ri - case 0x39: - - break; - - // cmpi simm - case 0x3c: - - break; - - // add a, s - case 0x40: - - break; - - // add a, (ri) - case 0x41: - - break; - - // mpya s, (ri), b - case 0x42: - - break; - - // add a, adr - case 0x43: - - break; - - // addi a, imm - case 0x44: - - - break; - - // add a, ((ri)) - case 0x45: - - break; - - // mod cond, op - case 0x48: - - break; - - // add a, ri - case 0x49: - - break; - - // mod f, op - case 0x4a: - - break; - - // mpya (rj), (ri), b - case 0x4b: - - break; - - // addi simm - case 0x4c: // docs show a wrong opcode value - - break; - - // ld reg, erij - case 0x4e: - case 0x4f: - - break; - - // and a, s - case 0x50: - - break; - - // and a, (ri) - case 0x51: - - break; - - // mld s, (ri), b - case 0x52: - break; - - // and a, adr - case 0x53: - - break; - - // andi a, imm - case 0x54: - - - break; - - // and a, ((ri)) - case 0x55: - - break; - - // and a, ri - case 0x59: - - break; - - // mld (rj), (ri), b - case 0x5b: - - break; - - // andi simm - case 0x5c: - A = (A & ~0x00ff0000) | (A & ((op & 0xff) << 16)); -// SET_L(); - SET_Z(A == 0); - SET_N(A >> 31); - SET_OV(0); - break; - - // ld erij, reg - case 0x5e: - case 0x5f: - - break; - - // or a, s - case 0x60: - - break; - - // or a, (ri) - case 0x61: - - break; - - // or a, adr - case 0x63: - - break; - - // ori a, imm - case 0x64: - - break; - - // or a, ((ri)) - case 0x65: - - break; - - // or a, ri - case 0x69: - - break; - - // ori simm - case 0x6c: - - break; - - // eor a, s - case 0x70: - - break; - - // eor a, (ri) - case 0x71: - - break; - - // eor a, adr - case 0x73: - - break; - - // eori a, imm - case 0x74: - - break; - - // eor a, ((ri)) - case 0x75: - - break; - - // eor a, ri - case 0x79: - - break; - - // eori simm - case 0x7c: - - break; - - default: - - break; - } - - ssp1610_ICount--; - - } while( ssp1610_ICount > 0 ); - - return cycles - ssp1610_ICount; -} - -static void ssp1610_get_context(void *regs) -{ - /* copy the context */ - if( regs ) - *(ssp1610_regs *)regs = ssp1610; -} - -static void ssp1610_set_context(void *regs) -{ - /* copy the context */ - if (regs) - ssp1610 = *(ssp1610_regs *)regs; -} - -#ifdef ENABLE_DEBUGGER -static offs_t ssp1610_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram) -{ - return dasm_ssp1610( buffer, pc, oprom); -} -#endif /* ENABLE_DEBUGGER */ - -#if (HAS_SSP1610) - -/************************************************************************** - * Generic set_info - **************************************************************************/ - -static void ssp1610_set_info(UINT32 state, cpuinfo *info) -{ - switch (state) - { - /* --- the following bits of info are set as 64-bit signed integers --- */ - -// case CPUINFO_INT_REGISTER + SSP1610_REG0: REG0 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_X: X = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_Y: Y = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_A: A = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_ST: ST = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_STACK: STACK = info->i; break; - case CPUINFO_INT_PC: - case CPUINFO_INT_REGISTER + SSP1610_PC: PC = info->i; change_pc(PC); break; - case CPUINFO_INT_REGISTER + SSP1610_P: P = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_AL: AL = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_XST: XST = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_PL: PL = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_SRCR: SRCR = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_BRCR: BRCR = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_BRER: BRER = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_XRD0: XRD0 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_XRD1: XRD1 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_AE: AE = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_DIOR: DIOR = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_GR22: GR22 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_GR23: GR23 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT0: EXT0 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT1: EXT1 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT2: EXT2 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT3: EXT3 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT4: EXT4 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT5: EXT5 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT6: EXT6 = info->i; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT7: EXT7 = info->i; break; - -// case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; -// case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break; -// case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(2, info->i); break; - } -} - -/************************************************************************** - * Generic get_info - **************************************************************************/ - -void ssp1610_get_info(UINT32 state, cpuinfo *info) -{ - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ssp1610_regs); break; - case CPUINFO_INT_INPUT_LINES: info->i = 3; break; - case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; - case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; 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 = 2; break; - case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; - case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; - case CPUINFO_INT_MAX_CYCLES: info->i = 3; break; - - case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; - case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break; - case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -1; break; - case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; - case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; - case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; - - case CPUINFO_INT_INPUT_STATE + 0: /* not implemented */ break; - - case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break; - - case CPUINFO_INT_REGISTER + SSP1610_REG0: info->i = REG0; break; - case CPUINFO_INT_REGISTER + SSP1610_X: info->i = X; break; - case CPUINFO_INT_REGISTER + SSP1610_Y: info->i = Y; break; - case CPUINFO_INT_REGISTER + SSP1610_A: info->i = A; break; - case CPUINFO_INT_REGISTER + SSP1610_ST: info->i = ST; break; - case CPUINFO_INT_REGISTER + SSP1610_STACK: info->i = STACK; break; - case CPUINFO_INT_PC: - case CPUINFO_INT_REGISTER + SSP1610_PC: info->i = PC; change_pc(PC); break; - case CPUINFO_INT_REGISTER + SSP1610_P: info->i = P; break; - case CPUINFO_INT_REGISTER + SSP1610_AL: info->i = AL; break; - case CPUINFO_INT_REGISTER + SSP1610_XST: info->i = XST; break; - case CPUINFO_INT_REGISTER + SSP1610_PL: info->i = PL; break; - case CPUINFO_INT_REGISTER + SSP1610_SRCR: info->i = SRCR; break; - case CPUINFO_INT_REGISTER + SSP1610_BRCR: info->i = BRCR; break; - case CPUINFO_INT_REGISTER + SSP1610_BRER: info->i = BRER; break; - case CPUINFO_INT_REGISTER + SSP1610_XRD0: info->i = XRD0; break; - case CPUINFO_INT_REGISTER + SSP1610_XRD1: info->i = XRD1; break; - case CPUINFO_INT_REGISTER + SSP1610_AE: info->i = AE; break; - case CPUINFO_INT_REGISTER + SSP1610_DIOR: info->i = DIOR; break; - case CPUINFO_INT_REGISTER + SSP1610_GR22: info->i = GR22; break; - case CPUINFO_INT_REGISTER + SSP1610_GR23: info->i = GR23; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT0: info->i = EXT0; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT1: info->i = EXT1; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT2: info->i = EXT2; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT3: info->i = EXT3; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT4: info->i = EXT4; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT5: info->i = EXT5; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT6: info->i = EXT6; break; - case CPUINFO_INT_REGISTER + SSP1610_EXT7: info->i = EXT7; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case CPUINFO_PTR_SET_INFO: info->setinfo = ssp1610_set_info; break; - case CPUINFO_PTR_GET_CONTEXT: info->getcontext = ssp1610_get_context; break; - case CPUINFO_PTR_SET_CONTEXT: info->setcontext = ssp1610_set_context; break; - case CPUINFO_PTR_INIT: info->init = ssp1610_init; break; - case CPUINFO_PTR_RESET: info->reset = ssp1610_reset; break; - case CPUINFO_PTR_EXIT: info->exit = ssp1610_exit; break; - case CPUINFO_PTR_EXECUTE: info->execute = ssp1610_execute; break; - case CPUINFO_PTR_BURN: info->burn = NULL; break; -#ifdef ENABLE_DEBUGGER - case CPUINFO_PTR_DISASSEMBLE: info->disassemble = ssp1610_dasm; break; -#endif /* ENABLE_DEBUGGER */ - case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ssp1610_ICount; break; - - case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map16 = NULL; break; - case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map16 = NULL; break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "SSP1610 CPU"); break; - case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.1"); break; - case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; - case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Pierpaolo Prazzoli"); break; - - case CPUINFO_STR_FLAGS: - sprintf(info->s, "_flags_"); - break; - - case CPUINFO_STR_REGISTER + SSP1610_REG0: sprintf(info->s, "REG0 :%04X", REG0); break; - case CPUINFO_STR_REGISTER + SSP1610_X: sprintf(info->s, "X :%04X", X); break; - case CPUINFO_STR_REGISTER + SSP1610_Y: sprintf(info->s, "Y :%04X", Y); break; - case CPUINFO_STR_REGISTER + SSP1610_A: sprintf(info->s, "A :%08X", A); break; - case CPUINFO_STR_REGISTER + SSP1610_ST: sprintf(info->s, "ST :%04X", ST); break; - case CPUINFO_STR_REGISTER + SSP1610_STACK: sprintf(info->s, "STACK :%04X", STACK); break; - case CPUINFO_STR_REGISTER + SSP1610_PC: sprintf(info->s, "PC :%04X", PC); break; - case CPUINFO_STR_REGISTER + SSP1610_P: sprintf(info->s, "P :%08X", P); break; - case CPUINFO_STR_REGISTER + SSP1610_AL: sprintf(info->s, "AL :%04X", AL); break; - case CPUINFO_STR_REGISTER + SSP1610_XST: sprintf(info->s, "XST :%04X", XST); break; - case CPUINFO_STR_REGISTER + SSP1610_PL: sprintf(info->s, "PL :%04X", PL); break; - case CPUINFO_STR_REGISTER + SSP1610_SRCR: sprintf(info->s, "SRCR :%02X", SRCR); break; - case CPUINFO_STR_REGISTER + SSP1610_BRCR: sprintf(info->s, "BRCR :%02X", BRCR); break; - case CPUINFO_STR_REGISTER + SSP1610_BRER: sprintf(info->s, "BRER :%04X", BRER); break; - case CPUINFO_STR_REGISTER + SSP1610_XRD0: sprintf(info->s, "XRD0 :%02X", XRD0); break; - case CPUINFO_STR_REGISTER + SSP1610_XRD1: sprintf(info->s, "XRD1 :%02X", XRD1); break; - case CPUINFO_STR_REGISTER + SSP1610_AE: sprintf(info->s, "AE :%02X", AE); break; - case CPUINFO_STR_REGISTER + SSP1610_DIOR: sprintf(info->s, "DIOR :%04X", DIOR); break; - case CPUINFO_STR_REGISTER + SSP1610_GR22: sprintf(info->s, "GR22 :%04X", GR22); break; - case CPUINFO_STR_REGISTER + SSP1610_GR23: sprintf(info->s, "GR23 :%04X", GR23); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT0: sprintf(info->s, "EXT0 :%04X", EXT0); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT1: sprintf(info->s, "EXT1 :%04X", EXT1); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT2: sprintf(info->s, "EXT2 :%04X", EXT2); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT3: sprintf(info->s, "EXT3 :%04X", EXT3); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT4: sprintf(info->s, "EXT4 :%04X", EXT4); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT5: sprintf(info->s, "EXT5 :%04X", EXT5); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT6: sprintf(info->s, "EXT6 :%04X", EXT6); break; - case CPUINFO_STR_REGISTER + SSP1610_EXT7: sprintf(info->s, "EXT7 :%04X", EXT7); break; - - } -} -#endif diff --git a/src/emu/cpu/ssp1610/ssp1610.h b/src/emu/cpu/ssp1610/ssp1610.h deleted file mode 100644 index b8e24f6dadd..00000000000 --- a/src/emu/cpu/ssp1610/ssp1610.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SSP1610_H -#define SSP1610_H - -#include "cpuintrf.h" - -/* Functions */ - -#if (HAS_SSP1610) -void ssp1610_get_info(UINT32 state, cpuinfo *info); -#endif - -#ifdef ENABLE_DEBUGGER -extern unsigned dasm_ssp1610(char *buffer, unsigned pc, const UINT8 *oprom); -#endif - -#endif /* SSP1610_H */ diff --git a/src/emu/cpu/ssp1610/ssp1610d.c b/src/emu/cpu/ssp1610/ssp1610d.c deleted file mode 100644 index 3ac58284ef6..00000000000 --- a/src/emu/cpu/ssp1610/ssp1610d.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - - SSP1610 disassembler - written by Pierpaolo Prazzoli - -*/ - -#include -#include "debugger.h" -#include "cpuintrf.h" - - -static const char *const reg[] = -{ - "-", "X", "Y", "A", "ST", "STACK", "PC", "P", "AL", "?", "?", "XST", "PL", "?", "?", "SRCR", "BRCR", "BRER", - "XRD0", "XRD1", "AE", "DIOR", "GR22", "GR23", "EXT0", "EXT1", "EXT2", "EXT3", "EXT4", "EXT5", "EXT6", "EXT7" -}; - -static const char *const rij[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" -}; - -static const char *const erij[] = -{ - "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7" -}; - -static const char *const modifier[] = -{ - "", "+!", "-", "+" -}; - -static const char *const cond[] = -{ - "always", "always", "RESERVED", "RESERVED", "gpi0=0", "gpi0=1", "gpi1=0", "gpi1=1", "l=0", "l=1", "z=0", "z=1", "ov=0", "ov=1", "n=0", "n=1", - "diof=0", "diof=1", "gpi2=0", "gpi2=1", "gpi3=0", "gpi3=1", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED" -}; - -static const char *const acc_op[] = -{ - "ror", "rol", "shr", "shl", "inc", "dec", "neg", "abs" -}; - -// pag. 81 uses different addresses! -static const char *const flag_op[] = -{ - "?", "?", "resl", "setl", "resie", "setie", "?", "?", "resop", "setop", "?", "?", "?", "?", "res", "set" -}; - - -static const char *const st_mod[] = -{ - "macs", "rpl", "gpo", "rb", "gpo0", "gpo1", "gpo2", "gpo3", "wte", "diof", "bre", "reserved", "reserved", "reserved", "reserved", "reserved" -}; - - -#define BIT_B ((op >> 8) & 1) -#define RIJ rij[(BIT_B << 2) + (op & 3)] -#define RI(i) rij[(i) & 3] -#define RJ(i) rij[((i) & 3) + 4] -#define MODIFIER(i) modifier[(i) & 3] -#define MODIFIER_LOW MODIFIER(op >> 2) -#define MODIFIER_HIGH MODIFIER(op >> 6) -#define COND cond[(op >> 4) & 0xf] - -static offs_t base_pc; -static const UINT8 *base_oprom; -#define READ_OP_DASM(p) ((base_oprom[(p) - base_pc] << 8) | base_oprom[(p) + 1 - base_pc]) - -//TODO: -// - add special Short-form Direct Addressing for r3 and r7 -// - support DASM flags - -unsigned dasm_ssp1610(char *buffer, unsigned pc, const UINT8 *oprom) -{ - UINT16 op; - UINT8 op_num; - int size = 1; - int flags = 0; - - base_pc = pc; - base_oprom = oprom; - - op = READ_OP_DASM(pc); - op_num = op >> 9; - - // .....overlapping opcodes.... - // - // ldi simm ? - // ld d, (a) ? - // mset reg, (ri), b ? overlaps other opcodes - // mset (rj), (ri), b ? - // repb simm/srcr, imm ? - // reps simm/srcr ? - // subi (rij)/erij/reg,imm,t ? - /* - // mod x, nimm, n - case 0x11: - sprintf(buffer, "mod x, %X, %d", op & 0xf, (op >> 4) & 1); - break; - - // mset (rj), (ri), ss - case 0x18, 0x19: // ss order? - sprintf(buffer, "mset (%s%s), (%s%s), %d%d", RJ(op >> 5), MODIFIER(op >> 7), RI(op), MODIFIER_LOW, (op >> 9) & 1, (op >> 4) & 1); - break; - - // mod st, bs, nimm - case 0x28: //? docs say 0x24 - sprintf(buffer, "mod st, %s, %x", st_mod[(op >> 5) & 0xf], op & 0xf); - break; - */ - - switch( op_num ) - { - - //???????????????????? - - // ldi simm -// case 0x08: -// sprintf(buffer, "ldi %X", op & 0xff); -// break; - - // maybe - // mod st, bs, nimm - case 0x25: //? docs say 0x24 - sprintf(buffer, "mod st, %s, %x", st_mod[(op >> 5) & 0xf], op & 0xf); - break; - - //???????????????????? - - case 0x00: - - if(op == 0) // right? - { - // nop - sprintf(buffer, "nop"); - } - else if((op & 0xff) == 0x65) - { - // ret - sprintf(buffer, "ret"); - } - else - { - // ld d, s - sprintf(buffer, "ld %s, %s", reg[(op >> 4) & 0xf], reg[0xf]); - } - - break; - - // ld d, (ri) -> probably right - case 0x01: // or ldi simm ? - sprintf(buffer, "ld %s, (%s%s)", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW); - break; - - // ld (ri), s - case 0x02: - sprintf(buffer, "ld (%s%s), %s", RIJ, MODIFIER_LOW, reg[(op >> 4) & 0xf]); - break; - - // ld a, addr - case 0x03: - sprintf(buffer, "ld a, %X", op & 0x1ff); - break; - - // ldi d, imm - case 0x04: - sprintf(buffer, "ld %s, %X", reg[(op >> 4) & 0xf], READ_OP_DASM(pc+2)); - size = 2; - break; - - // ld d, ((ri)) - case 0x05: - sprintf(buffer, "ld %s, ((%s%s))", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW); - break; - - // ldi (ri), imm - case 0x06: - sprintf(buffer, "ld (%s%s), %X", RIJ, MODIFIER_LOW, READ_OP_DASM(pc+2)); - size = 2; - break; - - // ld addr, a -> almost sure it's this one. some of the 1st 4 bits are set in the code - case 0x07: // or ld d, (a) ? - sprintf(buffer, "ld %X, a", op & 0x1ff); - break; - - // ld d, ri - case 0x09: - sprintf(buffer, "ld %s, %s%s", reg[(op >> 4) & 0xf], RIJ, MODIFIER_LOW); - break; - - // ld ri, s - case 0x0a: - sprintf(buffer, "ld %s%s, %s", RIJ, MODIFIER_LOW, reg[(op >> 4) & 0xf]); - break; - - // mpys (rj), (ri), b - case 0x0b: - sprintf(buffer, "mpya (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B); - break; - - // ldi ri, simm - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - sprintf(buffer, "ldi %s, %X", rij[(op >> 7) & 7], op & 0xff); - break; - - // sub a, s - case 0x10: - sprintf(buffer, "sub a, %s", reg[op & 0xf]); - break; - - // sub a, (ri) - case 0x11: - sprintf(buffer, "sub a, (%s%s)", RIJ, MODIFIER_LOW); - break; - - // mpys s, (ri), b - case 0x12: - sprintf(buffer, "mpya %s, (%s%s), %d", reg[(op >> 4) & 0xf], RI(op), MODIFIER_LOW, BIT_B); - break; - - // sub a, adr - case 0x13: - sprintf(buffer, "sub a, %X", op & 0xff); - break; - - // subi a, imm - case 0x14: - sprintf(buffer, "subi a, %X", READ_OP_DASM(pc+2)); - size = 2; - break; - - // sub a, ((ri)) - case 0x15: - sprintf(buffer, "sub a, ((%s%s))", RIJ, MODIFIER_LOW); - break; - - // sub a, ri - case 0x19: - sprintf(buffer, "sub a, %s%s", RIJ, MODIFIER_LOW); - break; - - // mset reg, (ri), s - case 0x1a: - case 0x1b: - sprintf(buffer, "mset %s, (%s%s), %d", reg[(op >> 5) & 0x1f], RI(op), MODIFIER_LOW, (op >> 4) & 1); - break; - - // subi simm - case 0x1c: - sprintf(buffer, "subi %X", op & 0xff); - break; - - // sub a, erij - case 0x23: - sprintf(buffer, "sub a, %s%s", erij[(op >> 2) & 7], MODIFIER(op)); - break; - - // call cond, addr - case 0x24: //f bit? - sprintf(buffer, "call %s, %X", COND, READ_OP_DASM(pc+2)); - size = 2; - break; - - // bra cond, addr - case 0x26: //f bit? - sprintf(buffer, "bra %s, %X", COND, READ_OP_DASM(pc+2)); - size = 2; - break; - - - case 0x28: - - if(op & 0x100) - { - // slow imm - sprintf(buffer, "slow %X", op & 0xf); - } - else - { - // stop - sprintf(buffer, "stop"); - } - - break; - - // cmp a, s - case 0x30: - sprintf(buffer, "cmp a, %s", reg[op & 0xf]); - break; - - // cmp a, (ri) - case 0x31: - sprintf(buffer, "cmp a, (%s%s)", RIJ, MODIFIER_LOW); - break; - - // cmp a, adr - case 0x33: - sprintf(buffer, "cmp a, %X", op & 0xff); - break; - - // cmpi a, imm - case 0x34: - sprintf(buffer, "cmpi a, %X", READ_OP_DASM(pc+2)); - size = 2; - break; - - // cmp a, ((ri)) - case 0x35: - sprintf(buffer, "cmp a, ((%s%s))", RIJ, MODIFIER_LOW); - break; - - // cmp a, ri - case 0x39: - sprintf(buffer, "cmp a, %s%s", RIJ, MODIFIER_LOW); - break; - - // cmpi simm - case 0x3c: - sprintf(buffer, "cmpi %X", op & 0xff); - break; - - // add a, s - case 0x40: - sprintf(buffer, "add a, %s", reg[op & 0xf]); - break; - - // add a, (ri) - case 0x41: - sprintf(buffer, "add a, (%s%s)", RIJ, MODIFIER_LOW); - break; - - // mpya s, (ri), b - case 0x42: - sprintf(buffer, "mpya %s, (%s%s), %d", reg[(op >> 4) & 0xf], RI(op), MODIFIER_LOW, BIT_B); - break; - - // add a, adr - case 0x43: - sprintf(buffer, "add a, %X", op & 0xff); - break; - - // addi a, imm - case 0x44: - //sprintf(buffer, "addi a, %X", READ_OP_DASM(pc+2)); - size = 2; - - if(op & 0x1ff) - sprintf(buffer, "addi a, %X (CHECK ME!)", READ_OP_DASM(pc+2)); - else - sprintf(buffer, "addi a, %X", READ_OP_DASM(pc+2)); - - break; - - // add a, ((ri)) - case 0x45: - sprintf(buffer, "add a, ((%s%s))", RIJ, MODIFIER_LOW); - break; - - // mod cond, op - case 0x48: - sprintf(buffer, "mod %s, %s", COND, acc_op[op & 7]); - break; - - // add a, ri - case 0x49: - sprintf(buffer, "add a, %s%s", RIJ, MODIFIER_LOW); - break; - - // mod f, op - case 0x4a: - sprintf(buffer, "%s", flag_op[op & 0xf]); - break; - - // mpya (rj), (ri), b - case 0x4b: - sprintf(buffer, "mpya (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B); - break; - - // addi simm - case 0x4c: // docs show a wrong opcode value - sprintf(buffer, "addi %X", op & 0xff); - break; - - // ld reg, erij - case 0x4e: - case 0x4f: - sprintf(buffer, "ld %s, %s%s", reg[(op >> 5) & 0x1f], erij[(op >> 2) & 7], MODIFIER(op)); - break; - - // and a, s - case 0x50: - sprintf(buffer, "and a, %s", reg[op & 0xf]); - break; - - // and a, (ri) - case 0x51: - sprintf(buffer, "and a, (%s%s)", RIJ, MODIFIER_LOW); - break; - - // mld s, (ri), b - case 0x52: - sprintf(buffer, "mld %s, (%s%s), %d", reg[(op >> 4) & 0xf], RI(op), MODIFIER_LOW, BIT_B); - break; - - // and a, adr - case 0x53: - sprintf(buffer, "and a, %X", op & 0xff); - break; - - // andi a, imm - case 0x54: -// sprintf(buffer, "andi a, %X", READ_OP_DASM(pc+2)); - size = 2; - - if(op & 0x1ff) - sprintf(buffer, "andi a, %X (CHECK ME!)", READ_OP_DASM(pc+2)); - else - sprintf(buffer, "andi a, %X", READ_OP_DASM(pc+2)); - - break; - - // and a, ((ri)) - case 0x55: - sprintf(buffer, "and a, ((%s%s))", RIJ, MODIFIER_LOW); - break; - - // and a, ri - case 0x59: - sprintf(buffer, "and a, %s%s", RIJ, MODIFIER_LOW); - break; - - // mld (rj), (ri), b - case 0x5b: - sprintf(buffer, "mld (%s%s), (%s%s), %d", RJ(op >> 4), MODIFIER_HIGH, RI(op), MODIFIER_LOW, BIT_B); - break; - - // andi simm - case 0x5c: - sprintf(buffer, "andi %X", op & 0xff); - break; - - // ld erij, reg - case 0x5e: - case 0x5f: - sprintf(buffer, "ld %s%s, %s", erij[(op >> 2) & 7], MODIFIER(op), reg[(op >> 5) & 0x1f]); - break; - - // or a, s - case 0x60: - sprintf(buffer, "or a, %s", reg[op & 0xf]); - break; - - // or a, (ri) - case 0x61: - sprintf(buffer, "or a, (%s%s)", RIJ, MODIFIER_LOW); - break; - - // or a, adr - case 0x63: - sprintf(buffer, "or a, %X", op & 0xff); - break; - - // ori a, imm - case 0x64: - sprintf(buffer, "ori a, %X", READ_OP_DASM(pc+2)); - size = 2; - break; - - // or a, ((ri)) - case 0x65: - sprintf(buffer, "or a, ((%s%s))", RIJ, MODIFIER_LOW); - break; - - // or a, ri - case 0x69: - sprintf(buffer, "or a, %s%s", RIJ, MODIFIER_LOW); - break; - - // ori simm - case 0x6c: - sprintf(buffer, "ori %X", op & 0xff); - break; - - // eor a, s - case 0x70: - sprintf(buffer, "eor a, %s", reg[op & 0xf]); - break; - - // eor a, (ri) - case 0x71: - sprintf(buffer, "eor a, (%s%s)", RIJ, MODIFIER_LOW); - break; - - // eor a, adr - case 0x73: - sprintf(buffer, "eor a, %X", op & 0xff); - break; - - // eori a, imm - case 0x74: - sprintf(buffer, "eori a, %X", READ_OP_DASM(pc+2)); - size = 2; - break; - - // eor a, ((ri)) - case 0x75: - sprintf(buffer, "eor a, ((%s%s))", RIJ, MODIFIER_LOW); - break; - - // eor a, ri - case 0x79: - sprintf(buffer, "eor a, %s%s", RIJ, MODIFIER_LOW); - break; - - // eori simm - case 0x7c: - sprintf(buffer, "eori %X", op & 0xff); - break; - - default: - sprintf(buffer, "OP = %02X",op_num); - break; - } - - return size | flags | DASMFLAG_SUPPORTED; -} diff --git a/src/emu/cpuexec.h b/src/emu/cpuexec.h index facc3d4497e..8381e796bde 100644 --- a/src/emu/cpuexec.h +++ b/src/emu/cpuexec.h @@ -239,7 +239,7 @@ enum _cpu_type CPU_MB8843, CPU_MB8844, CPU_MB86233, - CPU_SSP1610, + CPU_SSP1601, CPU_MINX, CPU_COUNT }; diff --git a/src/emu/cpuintrf.c b/src/emu/cpuintrf.c index a9fa191994d..0fd0d630763 100644 --- a/src/emu/cpuintrf.c +++ b/src/emu/cpuintrf.c @@ -211,7 +211,7 @@ void mb8842_get_info(UINT32 state, cpuinfo *info); void mb8843_get_info(UINT32 state, cpuinfo *info); void mb8844_get_info(UINT32 state, cpuinfo *info); void mb86233_get_info(UINT32 state, cpuinfo *info); -void ssp1610_get_info(UINT32 state, cpuinfo *info); +void ssp1601_get_info(UINT32 state, cpuinfo *info); void minx_get_info(UINT32 state, cpuinfo *info); @@ -818,8 +818,8 @@ static const struct #if (HAS_MB86233) { CPU_MB86233, mb86233_get_info }, #endif -#if (HAS_SSP1610) - { CPU_SSP1610, ssp1610_get_info }, +#if (HAS_SSP1601) + { CPU_SSP1601, ssp1601_get_info }, #endif #if (HAS_MINX) { CPU_MINX, minx_get_info }, diff --git a/src/mame/drivers/megadriv.c b/src/mame/drivers/megadriv.c index 8d5797c04e1..f94906ebf7c 100644 --- a/src/mame/drivers/megadriv.c +++ b/src/mame/drivers/megadriv.c @@ -557,7 +557,9 @@ static void update_megadrive_vdp_code_and_address(void) ((megadrive_vdp_command_part2 & 0x0003) << 14); } -static UINT16 get_word_from_68k_mem(UINT32 source) +static UINT16 (*vdp_get_word_from_68k_mem)(UINT32 source); + +static UINT16 vdp_get_word_from_68k_mem_default(UINT32 source) { if (( source >= 0x000000 ) && ( source <= 0x3fffff )) { @@ -642,7 +644,7 @@ static void megadrive_do_insta_68k_to_vram_dma(UINT32 source,int length) for (count = 0;count<(length>>1);count++) { - vdp_vram_write(get_word_from_68k_mem(source)); + vdp_vram_write(vdp_get_word_from_68k_mem(source)); source+=2; if (source>0xffffff) source = 0xe00000; } @@ -668,7 +670,7 @@ static void megadrive_do_insta_68k_to_cram_dma(UINT32 source,UINT16 length) { //if (megadrive_vdp_address>=0x80) return; // abandon - write_cram_value((megadrive_vdp_address&0x7e)>>1, get_word_from_68k_mem(source)); + write_cram_value((megadrive_vdp_address&0x7e)>>1, vdp_get_word_from_68k_mem(source)); source+=2; if (source>0xffffff) source = 0xfe0000; @@ -696,7 +698,7 @@ static void megadrive_do_insta_68k_to_vsram_dma(UINT32 source,UINT16 length) { if (megadrive_vdp_address>=0x80) return; // abandon - megadrive_vdp_vsram[(megadrive_vdp_address&0x7e)>>1] = get_word_from_68k_mem(source); + megadrive_vdp_vsram[(megadrive_vdp_address&0x7e)>>1] = vdp_get_word_from_68k_mem(source); source+=2; if (source>0xffffff) source = 0xfe0000; @@ -1401,8 +1403,9 @@ static WRITE8_HANDLER( megadriv_z80_YM2612_write ) } } -static emu_timer *io_timeout[2]; -static int io_stage[2]; +/* Megadrive / Genesis has 3 I/O ports */ +static emu_timer *io_timeout[3]; +static int io_stage[3]; static TIMER_CALLBACK( io_timeout0_timer_callback ) { @@ -1414,6 +1417,11 @@ static TIMER_CALLBACK( io_timeout1_timer_callback ) io_stage[1] = -1; } +static TIMER_CALLBACK( io_timeout2_timer_callback ) +{ + io_stage[2] = -1; +} + static void init_megadri6_io(void) { @@ -1423,6 +1431,8 @@ static void init_megadri6_io(void) io_timeout[1] = timer_alloc(io_timeout1_timer_callback, NULL); io_stage[1] = -1; + io_timeout[2] = timer_alloc(io_timeout2_timer_callback, NULL); + io_stage[2] = -1; } /* pointers to our io data read/write functions */ @@ -2555,10 +2565,405 @@ static ADDRESS_MAP_START( sh2slave_writemem, ADDRESS_SPACE_PROGRAM, 32 ) ADDRESS_MAP_END - - /****************************************** END 32X related *************************************/ +/****************************************** SVP related *****************************************/ + +/* + * Emulator of memory controller in SVP chip + * + * Copyright 2008, Grazvydas Ignotas + * based on RE work by Tasco Deluxe + * + * SSP1601 EXT registers are mapped as I/O ports due to their function + * (they are interfaced through external bus), and are named as follows + * (these are unofficial names, official ones are unknown): + * EXT0: PM0 - programmable register 0 + * EXT1: PM1 - ... 1 + * EXT2: PM2 - ... 2 + * EXT3: XST - external status. Can also act as PM. + * EXT4: PM4 - ... 4 + * EXT5: (unused) + * EXT6: PMC - programmable memory register control (PMAC). + * EXT7: AL - although internal to SSP1601, it still causes bus access + * + * Depending on GPO bits in status register, PM0, PM1, PM2 and XST can act as + * external status registers, os as programmable memory registers. PM4 always + * acts as PM register (independend on GPO bits). + */ + +#include "cpu/ssp1601/ssp1601.h" + +static struct svp_vars +{ + UINT8 *iram; // IRAM (0-0x7ff) + UINT8 *dram; // [0x20000]; + UINT32 pmac_read[6]; // read modes/addrs for PM0-PM5 + UINT32 pmac_write[6]; // write ... + PAIR pmc; + #define SSP_PMC_HAVE_ADDR 1 // address written to PMAC, waiting for mode + #define SSP_PMC_SET 2 // PMAC is set, PMx can be programmed + UINT32 emu_status; + UINT16 XST; // external status, mapped at a15000 and a15002 on 68k side. + UINT16 XST2; // status of XST (bit1 set when 68k writes to XST) +} svp; + +static int get_inc(int mode) +{ + int inc = (mode >> 11) & 7; + if (inc != 0) { + if (inc != 7) inc--; + inc = 1 << inc; // 0 1 2 4 8 16 32 128 + if (mode & 0x8000) inc = -inc; // decrement mode + } + return inc; +} + +INLINE void overwrite_write(UINT16 *dst, UINT16 d) +{ + if (d & 0xf000) { *dst &= ~0xf000; *dst |= d & 0xf000; } + if (d & 0x0f00) { *dst &= ~0x0f00; *dst |= d & 0x0f00; } + if (d & 0x00f0) { *dst &= ~0x00f0; *dst |= d & 0x00f0; } + if (d & 0x000f) { *dst &= ~0x000f; *dst |= d & 0x000f; } +} + +static UINT32 pm_io(int reg, int write, UINT32 d) +{ + if (svp.emu_status & SSP_PMC_SET) + { + svp.pmac_read[write ? reg + 6 : reg] = svp.pmc.d; + svp.emu_status &= ~SSP_PMC_SET; + return 0; + } + + // just in case + if (svp.emu_status & SSP_PMC_HAVE_ADDR) { + svp.emu_status &= ~SSP_PMC_HAVE_ADDR; + } + + if (reg == 4 || (activecpu_get_reg(SSP_ST) & 0x60)) + { + #define CADDR ((((mode<<16)&0x7f0000)|addr)<<1) + UINT16 *dram = (UINT16 *)svp.dram; + if (write) + { + int mode = svp.pmac_write[reg]>>16; + int addr = svp.pmac_write[reg]&0xffff; + if ((mode & 0x43ff) == 0x0018) // DRAM + { + int inc = get_inc(mode); + if (mode & 0x0400) { + overwrite_write(&dram[addr], d); + } else dram[addr] = d; + svp.pmac_write[reg] += inc; + } + else if ((mode & 0xfbff) == 0x4018) // DRAM, cell inc + { + if (mode & 0x0400) { + overwrite_write(&dram[addr], d); + } else dram[addr] = d; + svp.pmac_write[reg] += (addr&1) ? 31 : 1; + } + else if ((mode & 0x47ff) == 0x001c) // IRAM + { + int inc = get_inc(mode); + ((UINT16 *)svp.iram)[addr&0x3ff] = d; + svp.pmac_write[reg] += inc; + } + else + { + logerror("ssp FIXME: PM%i unhandled write mode %04x, [%06x] %04x\n", + reg, mode, CADDR, d); + } + } + else + { + int mode = svp.pmac_read[reg]>>16; + int addr = svp.pmac_read[reg]&0xffff; + if ((mode & 0xfff0) == 0x0800) // ROM, inc 1, verified to be correct + { + UINT16 *ROM = (UINT16 *) memory_region(REGION_CPU1); + svp.pmac_read[reg] += 1; + d = ROM[addr|((mode&0xf)<<16)]; + } + else if ((mode & 0x47ff) == 0x0018) // DRAM + { + int inc = get_inc(mode); + d = dram[addr]; + svp.pmac_read[reg] += inc; + } + else + { + logerror("ssp FIXME: PM%i unhandled read mode %04x, [%06x]\n", + reg, mode, CADDR); + d = 0; + } + } + + // PMC value corresponds to last PMR accessed (not sure). + svp.pmc.d = svp.pmac_read[write ? reg + 6 : reg]; + + return d; + } + + return (UINT32)-1; +} + +static READ16_HANDLER( read_PM0 ) +{ + UINT32 d = pm_io(0, 0, 0); + if (d != (UINT32)-1) return d; + d = svp.XST2; + svp.XST2 &= ~2; // ? + return d; +} + +static WRITE16_HANDLER( write_PM0 ) +{ + UINT32 r = pm_io(0, 1, data); + if (r != (UINT32)-1) return; + svp.XST2 = data; // ? +} + +static READ16_HANDLER( read_PM1 ) +{ + UINT32 r = pm_io(1, 0, 0); + if (r != (UINT32)-1) return r; + logerror("svp: PM1 acces in non PM mode?\n"); + return 0; +} + +static WRITE16_HANDLER( write_PM1 ) +{ + UINT32 r = pm_io(1, 1, data); + if (r != (UINT32)-1) return; + logerror("svp: PM1 acces in non PM mode?\n"); +} + +static READ16_HANDLER( read_PM2 ) +{ + UINT32 r = pm_io(2, 0, 0); + if (r != (UINT32)-1) return r; + logerror("svp: PM2 acces in non PM mode?\n"); + return 0; +} + +static WRITE16_HANDLER( write_PM2 ) +{ + UINT32 r = pm_io(2, 1, data); + if (r != (UINT32)-1) return; + logerror("svp: PM2 acces in non PM mode?\n"); +} + +static READ16_HANDLER( read_XST ) +{ + UINT32 d = pm_io(3, 0, 0); + if (d != (UINT32)-1) return d; + + return svp.XST; +} + +static WRITE16_HANDLER( write_XST ) +{ + UINT32 r = pm_io(3, 1, data); + if (r != (UINT32)-1) return; + + svp.XST2 |= 1; + svp.XST = data; +} + +static READ16_HANDLER( read_PM4 ) +{ + return pm_io(4, 0, 0); +} + +static WRITE16_HANDLER( write_PM4 ) +{ + pm_io(4, 1, data); +} + +static READ16_HANDLER( read_PMC ) +{ + if (svp.emu_status & SSP_PMC_HAVE_ADDR) { + svp.emu_status |= SSP_PMC_SET; + svp.emu_status &= ~SSP_PMC_HAVE_ADDR; + return ((svp.pmc.w.l << 4) & 0xfff0) | ((svp.pmc.w.l >> 4) & 0xf); + } else { + svp.emu_status |= SSP_PMC_HAVE_ADDR; + return svp.pmc.w.l; + } +} + +static WRITE16_HANDLER( write_PMC ) +{ + if (svp.emu_status & SSP_PMC_HAVE_ADDR) { + svp.emu_status |= SSP_PMC_SET; + svp.emu_status &= ~SSP_PMC_HAVE_ADDR; + svp.pmc.w.h = data; + } else { + svp.emu_status |= SSP_PMC_HAVE_ADDR; + svp.pmc.w.l = data; + } +} + +static READ16_HANDLER( read_AL ) +{ + svp.emu_status &= ~(SSP_PMC_SET|SSP_PMC_HAVE_ADDR); + return 0; +} + +static WRITE16_HANDLER( write_AL ) +{ +} + + + +static READ16_HANDLER( svp_68k_io_r ) +{ + UINT32 d; + switch (offset) + { + // 0xa15000, 0xa15002 + case 0: + case 1: return svp.XST; + // 0xa15004 + case 2: d = svp.XST2; svp.XST2 &= ~1; return d; + default: logerror("unhandled SVP reg read @ %x\n", offset<<1); + } + return 0; +} + +static WRITE16_HANDLER( svp_68k_io_w ) +{ + switch (offset) + { + // 0xa15000, 0xa15002 + case 0: + case 1: svp.XST = data; svp.XST2 |= 2; break; + // 0xa15006 + case 3: break; // possibly halts SSP1601 + default: logerror("unhandled SVP reg write %04x @ %x\n", data, offset<<1); + } +} + +static READ16_HANDLER( svp_68k_cell1_r ) +{ + // this is rewritten 68k test code + UINT32 a1 = offset; + a1 = (a1 & 0x7001) | ((a1 & 0x3e) << 6) | ((a1 & 0xfc0) >> 5); + return ((UINT16 *)svp.dram)[a1]; +} + +static READ16_HANDLER( svp_68k_cell2_r ) +{ + // this is rewritten 68k test code + UINT32 a1 = offset; + a1 = (a1 & 0x7801) | ((a1 & 0x1e) << 6) | ((a1 & 0x7e0) >> 4); + return ((UINT16 *)svp.dram)[a1]; +} + +static ADDRESS_MAP_START( svp_ssp_map, ADDRESS_SPACE_PROGRAM, 16 ) + AM_RANGE(0x0000 , 0x03ff) AM_READ(SMH_BANK3) + AM_RANGE(0x0400 , 0xffff) AM_READ(SMH_BANK4) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( svp_ext_map, ADDRESS_SPACE_IO, 16 ) + ADDRESS_MAP_GLOBAL_MASK(0xf) + AM_RANGE(0*2 , 0*2+1) AM_READWRITE(read_PM0, write_PM0) + AM_RANGE(1*2 , 1*2+1) AM_READWRITE(read_PM1, write_PM1) + AM_RANGE(2*2 , 2*2+1) AM_READWRITE(read_PM2, write_PM2) + AM_RANGE(3*2 , 3*2+1) AM_READWRITE(read_XST, write_XST) + AM_RANGE(4*2 , 4*2+1) AM_READWRITE(read_PM4, write_PM4) + AM_RANGE(6*2 , 6*2+1) AM_READWRITE(read_PMC, write_PMC) + AM_RANGE(7*2 , 7*2+1) AM_READWRITE(read_AL, write_AL) +ADDRESS_MAP_END + + +/* DMA read function for SVP */ +static UINT16 vdp_get_word_from_68k_mem_svp(UINT32 source) +{ + if ((source & 0xe00000) == 0x000000) + { + UINT16 *rom = (UINT16*)memory_region(REGION_CPU1); + source -= 2; // DMA latency + return rom[source >> 1]; + } + else if ((source & 0xfe0000) == 0x300000) + { + UINT16 *dram = (UINT16*)svp.dram; + source &= 0x1fffe; + source -= 2; + return dram[source >> 1]; + } + else if ((source & 0xe00000) == 0xe00000) + { + return megadrive_ram[(source&0xffff)>>1]; + } + else + { + mame_printf_debug("DMA Read unmapped %06x\n",source); + return mame_rand(Machine); + } +} + +/* emulate testmode plug */ +static UINT8 megadrive_io_read_data_port_svp(int portnum) +{ + if (portnum == 0 && readinputportbytag_safe("MEMORY_TEST", 0x00)) + { + return (megadrive_io_data_regs[0] & 0xc0); + } + return megadrive_io_read_data_port_3button(portnum); +} + +static void svp_init(void) +{ + UINT8 *ROM; + + memset(&svp, 0, sizeof(svp)); + + /* SVP stuff */ + svp.dram = auto_malloc(0x20000); + memory_install_readwrite16_handler(0, ADDRESS_SPACE_PROGRAM, 0x300000, 0x31ffff, 0, 0, SMH_BANK2, SMH_BANK2); + memory_set_bankptr( 2, svp.dram ); + memory_install_readwrite16_handler(0, ADDRESS_SPACE_PROGRAM, 0xa15000, 0xa150ff, 0, 0, svp_68k_io_r, svp_68k_io_w); + // "cell arrange" 1 and 2 + memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x390000, 0x39ffff, 0, 0, svp_68k_cell1_r); + memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x3a0000, 0x3affff, 0, 0, svp_68k_cell2_r); + + svp.iram = auto_malloc(0x800); + memory_set_bankptr( 3, svp.iram ); + /* SVP ROM just shares m68k region.. */ + ROM = memory_region(REGION_CPU1); + memory_set_bankptr( 4, ROM + 0x800 ); + + vdp_get_word_from_68k_mem = vdp_get_word_from_68k_mem_svp; + megadrive_io_read_data_port_ptr = megadrive_io_read_data_port_svp; +} + + +INPUT_PORTS_START( megdsvp ) + PORT_INCLUDE( megadriv ) + + PORT_START_TAG("MEMORY_TEST") /* special memtest mode */ + /* Region setting for Console */ + PORT_DIPNAME( 0x01, 0x00, DEF_STR( Test ) ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) +INPUT_PORTS_END + +MACHINE_DRIVER_START( megdsvp ) + MDRV_IMPORT_FROM(megadriv) + + MDRV_CPU_ADD(SSP1601, MASTER_CLOCK / 7 * 3) /* ~23 MHz (guessed) */ + MDRV_CPU_PROGRAM_MAP(svp_ssp_map, 0) + MDRV_CPU_IO_MAP(svp_ext_map, 0) + /* IRQs are not used by this CPU */ +MACHINE_DRIVER_END + + +/****************************************** END SVP related *************************************/ + static attotime time_elapsed_since_crap; @@ -4713,6 +5118,8 @@ static void megadriv_init_common(running_machine *machine) megadriv_backupram = NULL; megadriv_backupram_length = 0; + vdp_get_word_from_68k_mem = vdp_get_word_from_68k_mem_default; + cpunum_set_info_fct(0, CPUINFO_PTR_M68K_TAS_CALLBACK, (void *)megadriv_tas_callback); if ((machine->gamedrv->ipt==ipt_megadri6) || (machine->gamedrv->ipt==ipt_ssf2ghw)) @@ -4773,6 +5180,15 @@ DRIVER_INIT( megadrie ) hazemdchoice_megadriv_framerate = 50; } +DRIVER_INIT( megadsvp ) +{ + megadriv_init_common(machine); + svp_init(); + hazemdchoice_megadrive_region_export = 1; + hazemdchoice_megadrive_region_pal = 0; + hazemdchoice_megadriv_framerate = 60; +} + /* used by megatech */ static READ8_HANDLER( z80_unmapped_port_r ) diff --git a/src/mame/drivers/megadriv.h b/src/mame/drivers/megadriv.h index 54ae0304a5e..f7fa0ae4480 100644 --- a/src/mame/drivers/megadriv.h +++ b/src/mame/drivers/megadriv.h @@ -1,15 +1,18 @@ extern DRIVER_INIT( megadrie ); extern DRIVER_INIT( megadriv ); extern DRIVER_INIT( megadrij ); +extern DRIVER_INIT( megadsvp ); INPUT_PORTS_EXTERN(megadriv); INPUT_PORTS_EXTERN(aladbl); INPUT_PORTS_EXTERN(megadri6); INPUT_PORTS_EXTERN(ssf2ghw); +INPUT_PORTS_EXTERN(megdsvp); MACHINE_DRIVER_EXTERN(megadriv); MACHINE_DRIVER_EXTERN(megadpal); MACHINE_DRIVER_EXTERN(_32x); +MACHINE_DRIVER_EXTERN(megdsvp); extern UINT16* megadriv_backupram; extern int megadriv_backupram_length; diff --git a/src/mame/mame.mak b/src/mame/mame.mak index b55b402db88..4bf056a725f 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -188,7 +188,7 @@ CPUS += MB8842 CPUS += MB8843 CPUS += MB8844 CPUS += MB86233 -CPUS += SSP1610 +CPUS += SSP1601 CPUS += APEXC CPUS += CP1610 CPUS += F8