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