Improved SCU DSP disassembler

This commit is contained in:
Angelo Salese 2011-09-07 16:11:03 +00:00
parent e27d55610b
commit a840eec94e
2 changed files with 258 additions and 162 deletions

View File

@ -8,80 +8,199 @@
enum enum
{ {
EA_PDST = 1, EA_A = 1,
EA_XDST, EA_ALU,
EA_ADST, EA_D0,
EA_YDST, 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 { typedef struct {
char mnemonic[32]; char mnemonic[32];
int address_mode; int address_mode_1;
int address_mode_2;
int address_mode_3,
} SCUDSP_OPCODE; } SCUDSP_OPCODE;
static const SCUDSP_OPCODE alu_table[16] = static const SCUDSP_OPCODE alu_table[16] =
{ {
{ "NOP", 0, }, /* 0000 */ { "NOP", 0, 0, 0, }, /* 0000 */
{ "AND", 0, }, /* 0001 */ { "AND", 0, 0, 0, }, /* 0001 */
{ "OR ", 0, }, /* 0010 */ { "OR ", 0, 0, 0, }, /* 0010 */
{ "XOR", 0, }, /* 0011 */ { "XOR", 0, 0, 0, }, /* 0011 */
{ "ADD", 0, }, /* 0100 */ { "ADD", 0, 0, 0, }, /* 0100 */
{ "SUB", 0, }, /* 0101 */ { "SUB", 0, 0, 0, }, /* 0101 */
{ "AD2", 0, }, /* 0110 */ { "AD2", 0, 0, 0, }, /* 0110 */
{ "???", 0, }, /* 0111 */ { "???", 0, 0, 0, }, /* 0111 */
{ "SR ", 0, }, /* 1000 */ { "SR ", 0, 0, 0, }, /* 1000 */
{ "RR ", 0, }, /* 1001 */ { "RR ", 0, 0, 0, }, /* 1001 */
{ "SL ", 0, }, /* 1010 */ { "SL ", 0, 0, 0, }, /* 1010 */
{ "RL ", 0, }, /* 1011 */ { "RL ", 0, 0, 0, }, /* 1011 */
{ "???", 0, }, /* 1100 */ { "???", 0, 0, 0, }, /* 1100 */
{ "???", 0, }, /* 1101 */ { "???", 0, 0, 0, }, /* 1101 */
{ "???", 0, }, /* 1110 */ { "???", 0, 0, 0, }, /* 1110 */
{ "RL8", 0, }, /* 1111 */ { "RL8", 0, 0, 0, }, /* 1111 */
}; };
static const SCUDSP_OPCODE xbus_table[] = static const SCUDSP_OPCODE xbus_table[] =
{ {
{ "NOP", 0, }, /* 000 */ { "NOP", 0, 0, 0, }, /* 000 */
{ "???", 0, }, /* 001 */ { "???", 0, 0, 0, }, /* 001 */
{ "MOV MUL,P", 0, }, /* 010 */ { "MOV", EA_MUL, EA_P, 0, }, /* 010 */
{ "MOV", EA_PDST }, /* 011 */ //MOV %s,P { "MOV", EA_SRCMEMX, EA_P, 0, }, /* 011 */ //MOV %s,P
{ "MOV", EA_XDST }, /* 100 */ //MOV %s,X { "MOV", EA_SRCMEMX, EA_X, 0, }, /* 100 */ //MOV %s,X
{ "???", 0, }, /* 101 */ { "???", 0, 0, 0, }, /* 101 */
{ "???", 0, }, /* 110 */ { "???", 0, 0, 0, }, /* 110 */
{ "???", 0, }, /* 111 */ { "???", 0, 0, 0, }, /* 111 */
}; };
static const SCUDSP_OPCODE ybus_table[] = static const SCUDSP_OPCODE ybus_table[] =
{ {
{ "NOP", 0, }, /* 000 */ { "NOP", 0, 0, 0, }, /* 000 */
{ "CLR A", 0, }, /* 001 */ { "CLR", 0, EA_A, 0, }, /* 001 */
{ "MOV ALU,A", 0, }, /* 010 */ { "MOV", EA_ALU, EA_A, 0, }, /* 010 */
{ "MOV", EA_ADST, }, /* 011 */ //MOV %s,A { "MOV", EA_SRCMEMY, EA_A, 0, }, /* 011 */ //MOV %s,A
{ "MOV", EA_YDST, }, /* 100 */ //MOV %s,Y { "MOV", EA_SRCMEMY, EA_Y, 0, }, /* 100 */ //MOV %s,Y
{ "???", 0, }, /* 101 */ { "???", 0, 0, 0, }, /* 101 */
{ "???", 0, }, /* 110 */ { "???", 0, 0, 0, }, /* 110 */
{ "???", 0, }, /* 111 */ { "???", 0, 0, 0, }, /* 111 */
}; };
static const SCUDSP_OPCODE ybus_table[] = static const SCUDSP_OPCODE d1bus_table[] =
{ {
{ "NOP", 0, }, /* 000 */ { "NOP", 0, 0, 0, }, /* 00 */
{ "MOV", 0, }, /* 001 */ //MOV %I8,%d { "MOV", EA_IMM8, EA_DSTMEM, 0, }, /* 01 */ //MOV %I8,%d
{ "???", 0, }, /* 010 */ { "???", 0, 0, 0, }, /* 10 */
{ "MOV", 0, }, /* 011 */ //MOV %S,%d { "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 src_mem[] = static const char *const src_mem[] =
{ {
"M0", /* 000 */ "M0", /* 0000 */
"M1", /* 001 */ "M1", /* 0001 */
"M2", /* 010 */ "M2", /* 0010 */
"M3", /* 011 */ "M3", /* 0011 */
"MC0", /* 100 */ "MC0", /* 0100 */
"MC1", /* 101 */ "MC1", /* 0101 */
"MC2", /* 110 */ "MC2", /* 0110 */
"MC3", /* 111 */ "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 */
}; };
/*****************************************************************************/ /*****************************************************************************/
@ -103,6 +222,18 @@ static UINT32 fetch(void)
return *rombase++; 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) static UINT32 decode_opcode(UINT32 pc, const SCUDSP_OPCODE *op_table,UINT32 cur_opcode)
{ {
INT8 rel8; INT8 rel8;
@ -115,115 +246,51 @@ static UINT32 decode_opcode(UINT32 pc, const SCUDSP_OPCODE *op_table,UINT32 cur_
//else if (!strcmp(op_table->mnemonic, "rts") || !strcmp(op_table->mnemonic, "rti")) //else if (!strcmp(op_table->mnemonic, "rts") || !strcmp(op_table->mnemonic, "rti"))
// flags = DASMFLAG_STEP_OUT; // flags = DASMFLAG_STEP_OUT;
switch(op_table->address_mode) print("%s ", op_table->mnemonic);
switch(op_table->address_mode_1)
{ {
case EA_PDST: case EA_ALU: print("ALU "); break;
print("%s %s,P", op_table->mnemonic, src_mem[(cur_opcode & 0x00700000) >> 20]); case EA_IMM8: print("%02X ",cur_opcode & 0xff); break;
break; case EA_IMM18: print("%08X ",cur_opcode & 0x7ffff); break;
case EA_IMM25: print("%08X ",cur_opcode & 0x1ffffff); break;
case EA_XDST: case EA_MUL: print("MUL "); break;
print("%s %s,X", op_table->mnemonic, src_mem[(cur_opcode & 0x00700000) >> 20]); case EA_SRCMEMX: print("%s ", src_mem[(cur_opcode & 0x00700000) >> 20]); break;
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_ADST: case EA_D0: print("%d D0 ",add_table(cur_opcode)); break;
print("%s %s,A", op_table->mnemonic, src_mem[(cur_opcode & 0x0001c000) >> 14]); case EA_DMASRCMEM: print("%d %s ",add_table(cur_opcode),src_mem[(cur_opcode & 0x00000300) >> 8]); break;
break;
case EA_YDST:
print("%s %s,Y", op_table->mnemonic, src_mem[(cur_opcode & 0x0001c000) >> 14]);
break;
#if 0
case EA_IMM8:
imm8 = fetch();
print("%s 0x%02X", op_table->mnemonic, imm8);
break;
case EA_IMM16:
imm16 = fetch16();
print("%s 0x%04X", op_table->mnemonic, imm16);
break;
case EA_DIRECT:
imm8 = fetch();
print("%s (0x%04X)", op_table->mnemonic, imm8);
break;
case EA_EXT:
imm16 = fetch16();
print("%s (0x%04X)", op_table->mnemonic, imm16);
break;
case EA_IND_X:
imm8 = fetch();
print("%s (X+0x%02X)", op_table->mnemonic, imm8);
break;
case EA_REL:
rel8 = fetch();
print("%s [0x%04X]", op_table->mnemonic, pc+2+rel8);
break;
case EA_DIRECT_IMM8:
imm8 = fetch();
mask = fetch();
print("%s (0x%04X), 0x%02X", op_table->mnemonic, imm8, mask);
break;
case EA_IND_X_IMM8:
imm8 = fetch();
mask = fetch();
print("%s (X+0x%02X), 0x%02X", op_table->mnemonic, imm8, mask);
break;
case EA_DIRECT_IMM8_REL:
imm8 = fetch();
mask = fetch();
rel8 = fetch();
print("%s (0x%04X), 0x%02X, [0x%04X]", op_table->mnemonic, imm8, mask, pc+4+rel8);
break;
case EA_IND_X_IMM8_REL:
imm8 = fetch();
mask = fetch();
rel8 = fetch();
print("%s (X+0x%02X), 0x%02X, [0x%04X]", op_table->mnemonic, imm8, mask, pc+4+rel8);
break;
case EA_IND_Y:
imm8 = fetch();
print("%s (Y+0x%02X)", op_table->mnemonic, imm8);
break;
case EA_IND_Y_IMM8:
imm8 = fetch();
mask = fetch();
print("%s (Y+0x%02X), 0x%02X", op_table->mnemonic, imm8, mask);
break;
case EA_IND_Y_IMM8_REL:
imm8 = fetch();
mask = fetch();
rel8 = fetch();
print("%s (Y+0x%02X), 0x%02X, [0x%04X]", op_table->mnemonic, imm8, mask, pc+2+rel8);
break;
case PAGE2:
op2 = fetch();
return decode_opcode(pc, &opcode_table_page2[op2]);
case PAGE3:
op2 = fetch();
return decode_opcode(pc, &opcode_table_page3[op2]);
case PAGE4:
op2 = fetch();
return decode_opcode(pc, &opcode_table_page4[op2]);
#endif
default: default:
print("%s", op_table->mnemonic); 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; return flags;
@ -238,10 +305,39 @@ CPU_DISASSEMBLE( scudsp )
rombase = oprom; rombase = oprom;
opcode = fetch(); opcode = fetch();
flags = decode_opcode(pc, &alu_table [(opcode & 0x3c000000) >> 26],opcode); switch((opcode & 0xc0000000) >> 30)
flags |= decode_opcode(pc, &xbus_table [(opcode & 0x03800000) >> 23],opcode); {
flags |= decode_opcode(pc, &ybus_table [(opcode & 0x000e0000) >> 17],opcode); case 0: // operation
flags |= decode_opcode(pc, &d1bus_table[(opcode & 0x00003000) >> 12],opcode); 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; return (rombase-oprom) | flags | DASMFLAG_SUPPORTED;
} }

View File

@ -1221,7 +1221,7 @@ static void dsp_dasm_move_immediate( UINT32 op, char *buffer )
{ {
data[0] = op & 0x7FFFF; data[0] = op & 0x7FFFF;
data[1] = (op & 0x3C000000) >> 26; data[1] = (op & 0x3C000000) >> 26;
data[2] = (op & 0x3F80000 ) >> 18; data[2] = (op & 0x3F80000 ) >> 19;
dsp_dasm_prefix( MVI_Command[1], buffer, data ); /* TODO: bad mem*/ dsp_dasm_prefix( MVI_Command[1], buffer, data ); /* TODO: bad mem*/
} }
else else