diff options
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 |