summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/scudsp/scudspdasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/scudsp/scudspdasm.c')
-rw-r--r--trunk/src/emu/cpu/scudsp/scudspdasm.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/scudsp/scudspdasm.c b/trunk/src/emu/cpu/scudsp/scudspdasm.c
new file mode 100644
index 00000000000..b696f99f392
--- /dev/null
+++ b/trunk/src/emu/cpu/scudsp/scudspdasm.c
@@ -0,0 +1,343 @@
+/*
+ Sega Saturn SCU DSP disassembler
+
+ Written by Angelo Salese
+*/
+
+#include "emu.h"
+
+enum
+{
+ EA_A = 1,
+ EA_ALU,
+ EA_D0,
+ EA_IMM8,
+ EA_IMM18,
+ EA_IMM25,
+ EA_MUL,
+ EA_P,
+ EA_X,
+ EA_Y,
+ EA_SRCMEMX,
+ EA_SRCMEMY,
+ EA_SRCMEMD1,
+ EA_DMADSTMEM,
+ EA_DSTMEM,
+ EA_MVIDSTMEM,
+};
+
+typedef struct {
+ char mnemonic[32];
+ int address_mode_1;
+ int address_mode_2;
+ int address_mode_3,
+} SCUDSP_OPCODE;
+
+static const SCUDSP_OPCODE alu_table[16] =
+{
+ { "NOP", 0, 0, 0, }, /* 0000 */
+ { "AND", 0, 0, 0, }, /* 0001 */
+ { "OR ", 0, 0, 0, }, /* 0010 */
+ { "XOR", 0, 0, 0, }, /* 0011 */
+ { "ADD", 0, 0, 0, }, /* 0100 */
+ { "SUB", 0, 0, 0, }, /* 0101 */
+ { "AD2", 0, 0, 0, }, /* 0110 */
+ { "???", 0, 0, 0, }, /* 0111 */
+ { "SR ", 0, 0, 0, }, /* 1000 */
+ { "RR ", 0, 0, 0, }, /* 1001 */
+ { "SL ", 0, 0, 0, }, /* 1010 */
+ { "RL ", 0, 0, 0, }, /* 1011 */
+ { "???", 0, 0, 0, }, /* 1100 */
+ { "???", 0, 0, 0, }, /* 1101 */
+ { "???", 0, 0, 0, }, /* 1110 */
+ { "RL8", 0, 0, 0, }, /* 1111 */
+};
+
+static const SCUDSP_OPCODE xbus_table[] =
+{
+ { "NOP", 0, 0, 0, }, /* 000 */
+ { "???", 0, 0, 0, }, /* 001 */
+ { "MOV", EA_MUL, EA_P, 0, }, /* 010 */
+ { "MOV", EA_SRCMEMX, EA_P, 0, }, /* 011 */ //MOV %s,P
+ { "MOV", EA_SRCMEMX, EA_X, 0, }, /* 100 */ //MOV %s,X
+ { "???", 0, 0, 0, }, /* 101 */
+ { "???", 0, 0, 0, }, /* 110 */
+ { "???", 0, 0, 0, }, /* 111 */
+};
+
+static const SCUDSP_OPCODE ybus_table[] =
+{
+ { "NOP", 0, 0, 0, }, /* 000 */
+ { "CLR", 0, EA_A, 0, }, /* 001 */
+ { "MOV", EA_ALU, EA_A, 0, }, /* 010 */
+ { "MOV", EA_SRCMEMY, EA_A, 0, }, /* 011 */ //MOV %s,A
+ { "MOV", EA_SRCMEMY, EA_Y, 0, }, /* 100 */ //MOV %s,Y
+ { "???", 0, 0, 0, }, /* 101 */
+ { "???", 0, 0, 0, }, /* 110 */
+ { "???", 0, 0, 0, }, /* 111 */
+};
+
+static const SCUDSP_OPCODE d1bus_table[] =
+{
+ { "NOP", 0, 0, 0, }, /* 00 */
+ { "MOV", EA_IMM8, EA_DSTMEM, 0, }, /* 01 */ //MOV %I8,%d
+ { "???", 0, 0, 0, }, /* 10 */
+ { "MOV", EA_SRCMEMD1,0, 0, }, /* 11 */ //MOV %S,%d
+};
+
+static const SCUDSP_OPCODE mvi_table[] =
+{
+ { "MVI", EA_IMM25, EA_MVIDSTMEM, 0, }, /* 0 */ //"MVI %I,%d"
+ { "MVI", EA_IMM18, EA_MVIDSTMEM, EA_FLAGS, }, /* 1 */ //"MVI %I,%d,%f"
+};
+
+static const SCUDSP_OPCODE dma_table[] =
+{
+ { "DMA", EA_D0, EA_DMADSTMEM, EA_IMM8, }, /* 000 */ // "DMA%H%A D0,%M,%I",
+ { "DMA", EA_DMASRCMEM, EA_D0, EA_IMM8, }, /* 001 */ // "DMA%H%A %s,D0,%I",
+ { "DMA", 0, 0, 0, }, /* 010 */ // "DMA%H%A D0,%M,%s",
+ { "DMA", 0, 0, 0, }, /* 011 */ // "DMA%H%A %s,D0,%s",
+ { "DMAH", EA_D0, EA_DMADSTMEM, EA_IMM8, }, /* 100 */ // "DMA%H%A D0,%M,%I",
+ { "DMAH", EA_DMASRCMEM, EA_D0, EA_IMM8, }, /* 101 */ // "DMA%H%A %s,D0,%I",
+ { "DMAH", 0, 0, 0, }, /* 110 */ // "DMA%H%A D0,%M,%s",
+ { "DMAH", 0, 0, 0, }, /* 111 */ // "DMA%H%A %s,D0,%s",
+
+};
+
+static const SCUDSP_OPCODE jmp_table[] =
+{
+ { "JMP", EA_IMM8, 0, 0, }, /* 0 */ // unconditional
+ { "JMP", EA_IMM8, 0, EA_FLAGS, }, /* 1 */ // conditional
+};
+
+static const SCUDSP_OPCODE loop_table[] =
+{
+ { "BTM", 0, 0, 0, }, /* 00 */
+ { "LPS", 0, 0, 0, }, /* 01 */
+};
+
+static const SCUDSP_OPCODE end_table[] =
+{
+ { "END", 0, 0, 0, }, /* 00 */
+ { "ENDI",0, 0, 0, }, /* 01 */
+};
+
+
+static const char *const src_mem[] =
+{
+ "M0", /* 0000 */
+ "M1", /* 0001 */
+ "M2", /* 0010 */
+ "M3", /* 0011 */
+ "MC0", /* 0100 */
+ "MC1", /* 0101 */
+ "MC2", /* 0110 */
+ "MC3", /* 0111 */
+ "???", /* 1000 */
+ "ALL", /* 1001 */
+ "ALH", /* 1010 */
+ "???", /* 1011 */
+ "???", /* 1100 */
+ "???", /* 1101 */
+ "???", /* 1110 */
+ "???", /* 1111 */
+};
+
+static const char *const dst_mem[] =
+{
+ "MC0", /* 0000 */
+ "MC1", /* 0001 */
+ "MC2", /* 0010 */
+ "MC3", /* 0011 */
+ "RX", /* 0100 */
+ "PL", /* 0101 */
+ "RA0", /* 0110 */
+ "WA0", /* 0111 */
+ "???", /* 1000 */
+ "???", /* 1001 */
+ "LOP", /* 1010 */
+ "TOP", /* 1011 */
+ "CT0", /* 1100 */
+ "CT1", /* 1101 */
+ "CT2", /* 1110 */
+ "CT3", /* 1111 */
+};
+
+static const char *const mvi_dst_mem[] =
+{
+ "MC0", /* 0000 */
+ "MC1", /* 0001 */
+ "MC2", /* 0010 */
+ "MC3", /* 0011 */
+ "RX", /* 0100 */
+ "PL", /* 0101 */
+ "RA0", /* 0110 */
+ "WA0", /* 0111 */
+ "???", /* 1000 */
+ "???", /* 1001 */
+ "LOP", /* 1010 */
+ "???", /* 1011 */
+ "PC", /* 1100 */ //???
+ "???", /* 1101 */
+ "???", /* 1110 */
+ "???", /* 1111 */
+};
+
+static const char *const cond_flags[] =
+{
+ "??", /* 0000 */
+ "Z ", /* 0001 */
+ "S ", /* 0010 */
+ "ZS", /* 0011 */
+ "C ", /* 0100 */
+ "??", /* 0101 */
+ "??", /* 0110 */
+ "??", /* 0111 */
+ "T0", /* 1000 */
+ "??", /* 1001 */
+ "??", /* 1010 */
+ "??", /* 1011 */
+ "??", /* 1100 */
+ "??", /* 1101 */
+ "??", /* 1110 */
+ "??", /* 1111 */
+};
+
+/*****************************************************************************/
+
+static char *output;
+static const UINT32 *rombase;
+
+static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
+{
+ va_list vl;
+
+ va_start(vl, fmt);
+ output += vsprintf(output, fmt, vl);
+ va_end(vl);
+}
+
+static UINT32 fetch(void)
+{
+ return *rombase++;
+}
+
+static UINT8 add_table(UINT32 cur_opcode)
+{
+ UINT8 res = (cur_opcode & 0x00038000) >> 15;
+
+ if(res == 0)
+ res = 0;
+ else
+ res = 1 << (res-1);
+
+ return res;
+}
+
+static UINT32 decode_opcode(UINT32 pc, const SCUDSP_OPCODE *op_table,UINT32 cur_opcode)
+{
+ INT8 rel8;
+ UINT32 imm32;
+ UINT8 op2;
+ UINT32 flags = 0;
+
+ //if (!strcmp(op_table->mnemonic, "jsr") || !strcmp(op_table->mnemonic, "bsr"))
+ // flags = DASMFLAG_STEP_OVER;
+ //else if (!strcmp(op_table->mnemonic, "rts") || !strcmp(op_table->mnemonic, "rti"))
+ // flags = DASMFLAG_STEP_OUT;
+
+ print("%s ", op_table->mnemonic);
+
+ switch(op_table->address_mode_1)
+ {
+ case EA_ALU: print("ALU "); break;
+ case EA_IMM8: print("%02X ",cur_opcode & 0xff); break;
+ case EA_IMM18: print("%08X ",cur_opcode & 0x7ffff); break;
+ case EA_IMM25: print("%08X ",cur_opcode & 0x1ffffff); break;
+ case EA_MUL: print("MUL "); break;
+ case EA_SRCMEMX: print("%s ", src_mem[(cur_opcode & 0x00700000) >> 20]); break;
+ case EA_SRCMEMY: print("%s ", src_mem[(cur_opcode & 0x0001c000) >> 14]); break;
+ case EA_SRCMEMD1: print("%s ", src_mem[(cur_opcode & 0x0000000f) >> 0]); break;
+ case EA_D0: print("%d D0 ",add_table(cur_opcode)); break;
+ case EA_DMASRCMEM: print("%d %s ",add_table(cur_opcode),src_mem[(cur_opcode & 0x00000300) >> 8]); break;
+
+ default:
+ break;
+ }
+
+ switch(op_table->address_mode_2)
+ {
+ case EA_A: print("A"); break;
+ case EA_P: print("P"); break;
+ case EA_X: print("X"); break;
+ case EA_Y: print("Y"); break;
+ case EA_DSTMEM: print("%s ", dst_mem[(cur_opcode & 0x00000f00) >> 8]); break;
+ case EA_DMADSTMEM: print("%s ", dst_mem[(cur_opcode & 0x00000300) >> 8]); break;
+ case EA_MVIDSTMEM: print("%s ", mvi_dst_mem[(cur_opcode & 0x3c000000) >> 26]); break;
+ case EA_D0: print("D0 "); break;
+
+ default:
+ break;
+ }
+
+ switch(op_table->address_mode_3)
+ {
+ case EA_IMM8: print("%02X ",cur_opcode & 0xff); break;
+ case EA_FLAGS:
+ if(!((cur_opcode >> 19) & 0x20))
+ print("N");
+ print("%s ", cond_flags[(cur_opcode & 0x0780000) >> 19]);
+ break;
+
+ default:
+ break;
+ }
+
+ return flags;
+}
+
+CPU_DISASSEMBLE( scudsp )
+{
+ UINT32 flags = 0;
+ UINT8 opcode;
+
+ output = buffer;
+ rombase = oprom;
+
+ opcode = fetch();
+ switch((opcode & 0xc0000000) >> 30)
+ {
+ case 0: // operation
+ flags = decode_opcode(pc, &alu_table [(opcode & 0x3c000000) >> 26],opcode);
+ flags |= decode_opcode(pc, &xbus_table [(opcode & 0x03800000) >> 23],opcode);
+ flags |= decode_opcode(pc, &ybus_table [(opcode & 0x000e0000) >> 17],opcode);
+ flags |= decode_opcode(pc, &d1bus_table[(opcode & 0x00003000) >> 12],opcode);
+ break;
+ case 1: // unknown
+ print("???");
+ flags = 0;
+ break;
+ case 2: // move immediate
+ flags = decode_opcode(pc, &mvi_table [(opcode & 0x02000000) >> 25],opcode);
+ break;
+ case 3: // control
+ switch((opcode & 0x30000000) >> 28)
+ {
+ case 0:
+ flags = decode_opcode(pc, &dma_table [(opcode & 0x7000) >> 12],opcode);
+ break;
+ case 1:
+ flags = decode_opcode(pc, &jmp_table [(opcode & 0x2000000) >> 25],opcode);
+ break;
+ case 2:
+ flags = decode_opcode(pc, &loop_table [(opcode & 0x8000000) >> 27],opcode);
+ break;
+ case 3:
+ flags = decode_opcode(pc, &end_table [(opcode & 0x8000000) >> 27],opcode);
+ break;
+ }
+ break;
+ }
+
+ return (rombase-oprom) | flags | DASMFLAG_SUPPORTED;
+}