bsnes-plus/bsnes/snes/cpu/core/disassembler/disassembler.cpp

216 lines
6 KiB
C++

#ifdef CPUCORE_CPP
uint8 CPUcore::disassembler_read(uint32 addr)
{
return 0;
}
uint8 CPUcore::dreadb(uint32 addr) {
return disassembler_read(addr);
}
uint16 CPUcore::dreadw(uint32 addr) {
uint16 r;
r = dreadb(addr + 0) << 0;
r |= dreadb(addr + 1) << 8;
return r;
}
uint32 CPUcore::dreadl(uint32 addr) {
uint32 r;
r = dreadb(addr + 0) << 0;
r |= dreadb(addr + 1) << 8;
r |= dreadb(addr + 2) << 16;
return r;
}
uint32 CPUcore::decode(uint8 offset_type, uint32 addr, uint32 pc) {
uint32 r = 0;
switch(offset_type) {
case SNESCPU::Direct:
r = (regs.d + (addr & 0xff)) & 0xffff;
break;
case SNESCPU::DirectX:
r = (regs.d + regs.x + (addr & 0xff)) & 0xffff;
break;
case SNESCPU::DirectY:
r = (regs.d + regs.y + (addr & 0xff)) & 0xffff;
break;
case SNESCPU::IDirect:
addr = (regs.d + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case SNESCPU::IDirectX:
addr = (regs.d + regs.x + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr);
break;
case SNESCPU::IDirectY:
addr = (regs.d + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case SNESCPU::ILDirect:
addr = (regs.d + (addr & 0xff)) & 0xffff;
r = dreadl(addr);
break;
case SNESCPU::ILDirectY:
addr = (regs.d + (addr & 0xff)) & 0xffff;
r = dreadl(addr) + regs.y;
break;
case SNESCPU::Address:
r = (regs.db << 16) + (addr & 0xffff);
break;
case SNESCPU::PAddress:
r = (pc & 0xff0000) + (addr & 0xffff);
break;
case SNESCPU::AddressX:
r = (regs.db << 16) + (addr & 0xffff) + regs.x;
break;
case SNESCPU::AddressY:
r = (regs.db << 16) + (addr & 0xffff) + regs.y;
break;
case SNESCPU::PIAddress:
r = (pc & 0xff0000) + (addr & 0xffff);
break;
case SNESCPU::IAddressX:
r = (pc & 0xff0000) + ((addr + regs.x) & 0xffff);
break;
case SNESCPU::ILAddress:
r = addr;
break;
case SNESCPU::Long:
r = addr;
break;
case SNESCPU::LongX:
r = (addr + regs.x);
break;
case SNESCPU::Stack:
r = (regs.s + (addr & 0xff)) & 0xffff;
break;
case SNESCPU::IStackY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + dreadw(addr) + regs.y;
break;
case SNESCPU::RelativeShort:
r = (pc & 0xff0000) + (((pc & 0xffff)+ 2) & 0xffff);
r += int8(addr);
break;
case SNESCPU::RelativeLong:
r = (pc & 0xff0000) + (((pc & 0xffff) + 3) & 0xffff);
r += int16(addr);
break;
}
return(r & 0xffffff);
}
void CPUcore::disassemble_opcode_ex(CPUcore::Opcode &opcode, uint32 addr, bool e, bool m, bool x) {
static reg24_t pc;
pc.d = addr;
uint8 param[4];
param[0] = dreadb(pc.d); pc.w++;
param[1] = dreadb(pc.d); pc.w++;
param[2] = dreadb(pc.d); pc.w++;
param[3] = dreadb(pc.d);
const SNESCPU::OpcodeInfo& op = cpuOpcodeInfo[param[0]];
opcode.set(0, op.mode, op.name, param,
SNESCPU::getOpcodeLength(e || m, e || x, param[0]) - 1);
switch (param[0]) {
case 0x00:
opcode.flags |= Opcode::FLAG_BRK; break;
case 0x08:
opcode.flags |= Opcode::FLAG_PUSH_P; break;
case 0x10: case 0x20: case 0x22: case 0x30:
case 0x50: case 0x70: case 0x90: case 0xb0:
case 0xd0: case 0xf0: case 0xfc:
opcode.flags |= Opcode::FLAG_BRA_CONTINUE; break;
case 0x28:
opcode.flags |= Opcode::FLAG_POP_P; break;
case 0x40: case 0x60: case 0x6b:
opcode.flags |= Opcode::FLAG_RETURN; break;
case 0x4c: case 0x5c: case 0x6c: case 0x7c:
case 0x80: case 0x82: case 0xdc:
opcode.flags |= Opcode::FLAG_BRA; break;
case 0xc2:
if (opcode.op8() & 0x10) opcode.flags |= Opcode::FLAG_RESET_X;
if (opcode.op8() & 0x20) opcode.flags |= Opcode::FLAG_RESET_M;
break;
case 0xdb:
opcode.flags |= Opcode::FLAG_HALT; break;
case 0xe2:
if (opcode.op8() & 0x10) opcode.flags |= Opcode::FLAG_SET_X;
if (opcode.op8() & 0x20) opcode.flags |= Opcode::FLAG_SET_M;
break;
case 0xfb:
opcode.flags |= Opcode::FLAG_RESET_E; break;
}
if (SNESCPU::getOpcodeIndirect(param[0])) {
opcode.flags |= Opcode::FLAG_INDIRECT;
}
}
void CPUcore::disassemble_opcode(char *output, uint32 addr, bool hclocks) {
static reg24_t pc;
char t[256];
char *s = output;
pc.d = addr;
sprintf(s, "%.6x ", (uint32)pc.d);
uint8 op = dreadb(pc.d); pc.w++;
uint8 op0 = dreadb(pc.d); pc.w++;
uint8 op1 = dreadb(pc.d); pc.w++;
uint8 op2 = dreadb(pc.d);
#define op24 ((op0) | (op1 << 8) | (op2 << 16))
#define a8 (regs.e || regs.p.m)
#define x8 (regs.e || regs.p.x)
unsigned op_mode = cpuOpcodeInfo[op].mode;
unsigned op_len = SNESCPU::getOpcodeLength(a8, x8, op);
sprintf(t, "%-14s ", SNESCPU::disassemble(addr, a8, x8, op, op0, op1, op2)());
strcat(s, t);
if (op_mode < SNESCPU::Direct || op_mode == SNESCPU::BlockMove)
sprintf(t, " ");
else
sprintf(t, "[%.6x] ", decode(op_mode, op24, addr));
strcat(s, t);
#undef op24
#undef a8
#undef x8
sprintf(t, "A:%.4x X:%.4x Y:%.4x S:%.4x D:%.4x DB:%.2x ",
regs.a.w, regs.x.w, regs.y.w, regs.s.w, regs.d.w, regs.db);
strcat(s, t);
if(regs.e) {
sprintf(t, "%c%c%c%c%c%c%c%c ",
regs.p.n ? 'N' : '.', regs.p.v ? 'V' : '.',
regs.p.m ? '1' : '.', regs.p.x ? 'B' : '.',
regs.p.d ? 'D' : '.', regs.p.i ? 'I' : '.',
regs.p.z ? 'Z' : '.', regs.p.c ? 'C' : '.');
} else {
sprintf(t, "%c%c%c%c%c%c%c%c ",
regs.p.n ? 'N' : '.', regs.p.v ? 'V' : '.',
regs.p.m ? 'M' : '.', regs.p.x ? 'X' : '.',
regs.p.d ? 'D' : '.', regs.p.i ? 'I' : '.',
regs.p.z ? 'Z' : '.', regs.p.c ? 'C' : '.');
}
strcat(s, t);
if (hclocks)
sprintf(t, "V:%3d H:%4d F:%2d", cpu.vcounter(), cpu.hcounter(), cpu.framecounter());
else
sprintf(t, "V:%3d H:%3d F:%2d", cpu.vcounter(), cpu.hdot(), cpu.framecounter());
strcat(s, t);
}
#endif