mirror of
https://github.com/devinacker/bsnes-plus.git
synced 2025-04-02 10:52:46 -04:00
216 lines
6 KiB
C++
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
|