2
Sega Saturn SCU DSP disassembler
4
Written by Angelo Salese
36
static const SCUDSP_OPCODE alu_table[16] =
38
{ "NOP", 0, 0, 0, }, /* 0000 */
39
{ "AND", 0, 0, 0, }, /* 0001 */
40
{ "OR ", 0, 0, 0, }, /* 0010 */
41
{ "XOR", 0, 0, 0, }, /* 0011 */
42
{ "ADD", 0, 0, 0, }, /* 0100 */
43
{ "SUB", 0, 0, 0, }, /* 0101 */
44
{ "AD2", 0, 0, 0, }, /* 0110 */
45
{ "???", 0, 0, 0, }, /* 0111 */
46
{ "SR ", 0, 0, 0, }, /* 1000 */
47
{ "RR ", 0, 0, 0, }, /* 1001 */
48
{ "SL ", 0, 0, 0, }, /* 1010 */
49
{ "RL ", 0, 0, 0, }, /* 1011 */
50
{ "???", 0, 0, 0, }, /* 1100 */
51
{ "???", 0, 0, 0, }, /* 1101 */
52
{ "???", 0, 0, 0, }, /* 1110 */
53
{ "RL8", 0, 0, 0, }, /* 1111 */
56
static const SCUDSP_OPCODE xbus_table[] =
58
{ "NOP", 0, 0, 0, }, /* 000 */
59
{ "???", 0, 0, 0, }, /* 001 */
60
{ "MOV", EA_MUL, EA_P, 0, }, /* 010 */
61
{ "MOV", EA_SRCMEMX, EA_P, 0, }, /* 011 */ //MOV %s,P
62
{ "MOV", EA_SRCMEMX, EA_X, 0, }, /* 100 */ //MOV %s,X
63
{ "???", 0, 0, 0, }, /* 101 */
64
{ "???", 0, 0, 0, }, /* 110 */
65
{ "???", 0, 0, 0, }, /* 111 */
68
static const SCUDSP_OPCODE ybus_table[] =
70
{ "NOP", 0, 0, 0, }, /* 000 */
71
{ "CLR", 0, EA_A, 0, }, /* 001 */
72
{ "MOV", EA_ALU, EA_A, 0, }, /* 010 */
73
{ "MOV", EA_SRCMEMY, EA_A, 0, }, /* 011 */ //MOV %s,A
74
{ "MOV", EA_SRCMEMY, EA_Y, 0, }, /* 100 */ //MOV %s,Y
75
{ "???", 0, 0, 0, }, /* 101 */
76
{ "???", 0, 0, 0, }, /* 110 */
77
{ "???", 0, 0, 0, }, /* 111 */
80
static const SCUDSP_OPCODE d1bus_table[] =
82
{ "NOP", 0, 0, 0, }, /* 00 */
83
{ "MOV", EA_IMM8, EA_DSTMEM, 0, }, /* 01 */ //MOV %I8,%d
84
{ "???", 0, 0, 0, }, /* 10 */
85
{ "MOV", EA_SRCMEMD1,0, 0, }, /* 11 */ //MOV %S,%d
88
static const SCUDSP_OPCODE mvi_table[] =
90
{ "MVI", EA_IMM25, EA_MVIDSTMEM, 0, }, /* 0 */ //"MVI %I,%d"
91
{ "MVI", EA_IMM18, EA_MVIDSTMEM, EA_FLAGS, }, /* 1 */ //"MVI %I,%d,%f"
94
static const SCUDSP_OPCODE dma_table[] =
96
{ "DMA", EA_D0, EA_DMADSTMEM, EA_IMM8, }, /* 000 */ // "DMA%H%A D0,%M,%I",
97
{ "DMA", EA_DMASRCMEM, EA_D0, EA_IMM8, }, /* 001 */ // "DMA%H%A %s,D0,%I",
98
{ "DMA", 0, 0, 0, }, /* 010 */ // "DMA%H%A D0,%M,%s",
99
{ "DMA", 0, 0, 0, }, /* 011 */ // "DMA%H%A %s,D0,%s",
100
{ "DMAH", EA_D0, EA_DMADSTMEM, EA_IMM8, }, /* 100 */ // "DMA%H%A D0,%M,%I",
101
{ "DMAH", EA_DMASRCMEM, EA_D0, EA_IMM8, }, /* 101 */ // "DMA%H%A %s,D0,%I",
102
{ "DMAH", 0, 0, 0, }, /* 110 */ // "DMA%H%A D0,%M,%s",
103
{ "DMAH", 0, 0, 0, }, /* 111 */ // "DMA%H%A %s,D0,%s",
107
static const SCUDSP_OPCODE jmp_table[] =
109
{ "JMP", EA_IMM8, 0, 0, }, /* 0 */ // unconditional
110
{ "JMP", EA_IMM8, 0, EA_FLAGS, }, /* 1 */ // conditional
113
static const SCUDSP_OPCODE loop_table[] =
115
{ "BTM", 0, 0, 0, }, /* 00 */
116
{ "LPS", 0, 0, 0, }, /* 01 */
119
static const SCUDSP_OPCODE end_table[] =
121
{ "END", 0, 0, 0, }, /* 00 */
122
{ "ENDI",0, 0, 0, }, /* 01 */
126
static const char *const src_mem[] =
146
static const char *const dst_mem[] =
166
static const char *const mvi_dst_mem[] =
180
"PC", /* 1100 */ //???
186
static const char *const cond_flags[] =
206
/*****************************************************************************/
209
static const UINT32 *rombase;
211
static void ATTR_PRINTF(1,2) print(const char *fmt, ...)
216
output += vsprintf(output, fmt, vl);
220
static UINT32 fetch(void)
225
static UINT8 add_table(UINT32 cur_opcode)
227
UINT8 res = (cur_opcode & 0x00038000) >> 15;
237
static UINT32 decode_opcode(UINT32 pc, const SCUDSP_OPCODE *op_table,UINT32 cur_opcode)
244
//if (!strcmp(op_table->mnemonic, "jsr") || !strcmp(op_table->mnemonic, "bsr"))
245
// flags = DASMFLAG_STEP_OVER;
246
//else if (!strcmp(op_table->mnemonic, "rts") || !strcmp(op_table->mnemonic, "rti"))
247
// flags = DASMFLAG_STEP_OUT;
249
print("%s ", op_table->mnemonic);
251
switch(op_table->address_mode_1)
253
case EA_ALU: print("ALU "); break;
254
case EA_IMM8: print("%02X ",cur_opcode & 0xff); break;
255
case EA_IMM18: print("%08X ",cur_opcode & 0x7ffff); break;
256
case EA_IMM25: print("%08X ",cur_opcode & 0x1ffffff); break;
257
case EA_MUL: print("MUL "); break;
258
case EA_SRCMEMX: print("%s ", src_mem[(cur_opcode & 0x00700000) >> 20]); break;
259
case EA_SRCMEMY: print("%s ", src_mem[(cur_opcode & 0x0001c000) >> 14]); break;
260
case EA_SRCMEMD1: print("%s ", src_mem[(cur_opcode & 0x0000000f) >> 0]); break;
261
case EA_D0: print("%d D0 ",add_table(cur_opcode)); break;
262
case EA_DMASRCMEM: print("%d %s ",add_table(cur_opcode),src_mem[(cur_opcode & 0x00000300) >> 8]); break;
268
switch(op_table->address_mode_2)
270
case EA_A: print("A"); break;
271
case EA_P: print("P"); break;
272
case EA_X: print("X"); break;
273
case EA_Y: print("Y"); break;
274
case EA_DSTMEM: print("%s ", dst_mem[(cur_opcode & 0x00000f00) >> 8]); break;
275
case EA_DMADSTMEM: print("%s ", dst_mem[(cur_opcode & 0x00000300) >> 8]); break;
276
case EA_MVIDSTMEM: print("%s ", mvi_dst_mem[(cur_opcode & 0x3c000000) >> 26]); break;
277
case EA_D0: print("D0 "); break;
283
switch(op_table->address_mode_3)
285
case EA_IMM8: print("%02X ",cur_opcode & 0xff); break;
287
if(!((cur_opcode >> 19) & 0x20))
289
print("%s ", cond_flags[(cur_opcode & 0x0780000) >> 19]);
299
CPU_DISASSEMBLE( scudsp )
308
switch((opcode & 0xc0000000) >> 30)
311
flags = decode_opcode(pc, &alu_table [(opcode & 0x3c000000) >> 26],opcode);
312
flags |= decode_opcode(pc, &xbus_table [(opcode & 0x03800000) >> 23],opcode);
313
flags |= decode_opcode(pc, &ybus_table [(opcode & 0x000e0000) >> 17],opcode);
314
flags |= decode_opcode(pc, &d1bus_table[(opcode & 0x00003000) >> 12],opcode);
320
case 2: // move immediate
321
flags = decode_opcode(pc, &mvi_table [(opcode & 0x02000000) >> 25],opcode);
324
switch((opcode & 0x30000000) >> 28)
327
flags = decode_opcode(pc, &dma_table [(opcode & 0x7000) >> 12],opcode);
330
flags = decode_opcode(pc, &jmp_table [(opcode & 0x2000000) >> 25],opcode);
333
flags = decode_opcode(pc, &loop_table [(opcode & 0x8000000) >> 27],opcode);
336
flags = decode_opcode(pc, &end_table [(opcode & 0x8000000) >> 27],opcode);
342
return (rombase-oprom) | flags | DASMFLAG_SUPPORTED;