diff options
author | 2008-03-13 15:35:17 +0000 | |
---|---|---|
committer | 2008-03-13 15:35:17 +0000 | |
commit | 3a082a644f6fc1fcd0c5760e96572870ae26af3f (patch) | |
tree | 6de6198e689160e7e5e1755b4ae7655a32ea6c02 /src/emu/cpu/ssp1601 | |
parent | 49c8a68835d95f054f44c1d4a9c6a1d2a88c3c57 (diff) |
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).
Diffstat (limited to 'src/emu/cpu/ssp1601')
-rw-r--r-- | src/emu/cpu/ssp1601/ssp1601.c | 918 | ||||
-rw-r--r-- | src/emu/cpu/ssp1601/ssp1601.h | 24 | ||||
-rw-r--r-- | src/emu/cpu/ssp1601/ssp1601d.c | 290 |
3 files changed, 1232 insertions, 0 deletions
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 <math.h> +#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 |