mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2024-06-01 19:17:33 -04:00
973 lines
34 KiB
C++
973 lines
34 KiB
C++
// Processor debug commands.
|
|
#include "pch.h"
|
|
|
|
namespace Debug
|
|
{
|
|
// Run processor until break or stop
|
|
static Json::Value* CmdRun(std::vector<std::string>& args)
|
|
{
|
|
Core->Run();
|
|
return nullptr;
|
|
}
|
|
|
|
// Stop processor execution
|
|
static Json::Value* CmdStop(std::vector<std::string>& args)
|
|
{
|
|
if (Core->IsRunning())
|
|
{
|
|
Core->Suspend();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
// r
|
|
|
|
// Get pointer to Gekko register.
|
|
static uint32_t* getreg(const char* name)
|
|
{
|
|
if (!_stricmp(name, "r0")) return &Core->regs.gpr[0];
|
|
else if (!_stricmp(name, "r1")) return &Core->regs.gpr[1];
|
|
else if (!_stricmp(name, "r2")) return &Core->regs.gpr[2];
|
|
else if (!_stricmp(name, "r3")) return &Core->regs.gpr[3];
|
|
else if (!_stricmp(name, "r4")) return &Core->regs.gpr[4];
|
|
else if (!_stricmp(name, "r5")) return &Core->regs.gpr[5];
|
|
else if (!_stricmp(name, "r6")) return &Core->regs.gpr[6];
|
|
else if (!_stricmp(name, "r7")) return &Core->regs.gpr[7];
|
|
else if (!_stricmp(name, "r8")) return &Core->regs.gpr[8];
|
|
else if (!_stricmp(name, "r9")) return &Core->regs.gpr[9];
|
|
else if (!_stricmp(name, "r10")) return &Core->regs.gpr[10];
|
|
else if (!_stricmp(name, "r11")) return &Core->regs.gpr[11];
|
|
else if (!_stricmp(name, "r12")) return &Core->regs.gpr[12];
|
|
else if (!_stricmp(name, "r13")) return &Core->regs.gpr[13];
|
|
else if (!_stricmp(name, "r14")) return &Core->regs.gpr[14];
|
|
else if (!_stricmp(name, "r15")) return &Core->regs.gpr[15];
|
|
else if (!_stricmp(name, "r16")) return &Core->regs.gpr[16];
|
|
else if (!_stricmp(name, "r17")) return &Core->regs.gpr[17];
|
|
else if (!_stricmp(name, "r18")) return &Core->regs.gpr[18];
|
|
else if (!_stricmp(name, "r19")) return &Core->regs.gpr[19];
|
|
else if (!_stricmp(name, "r20")) return &Core->regs.gpr[20];
|
|
else if (!_stricmp(name, "r21")) return &Core->regs.gpr[21];
|
|
else if (!_stricmp(name, "r22")) return &Core->regs.gpr[22];
|
|
else if (!_stricmp(name, "r23")) return &Core->regs.gpr[23];
|
|
else if (!_stricmp(name, "r24")) return &Core->regs.gpr[24];
|
|
else if (!_stricmp(name, "r25")) return &Core->regs.gpr[25];
|
|
else if (!_stricmp(name, "r26")) return &Core->regs.gpr[26];
|
|
else if (!_stricmp(name, "r27")) return &Core->regs.gpr[27];
|
|
else if (!_stricmp(name, "r28")) return &Core->regs.gpr[28];
|
|
else if (!_stricmp(name, "r29")) return &Core->regs.gpr[29];
|
|
else if (!_stricmp(name, "r30")) return &Core->regs.gpr[30];
|
|
else if (!_stricmp(name, "r31")) return &Core->regs.gpr[31];
|
|
|
|
else if (!_stricmp(name, "sp")) return &Core->regs.gpr[1];
|
|
else if (!_stricmp(name, "sd1")) return &Core->regs.gpr[13];
|
|
else if (!_stricmp(name, "sd2")) return &Core->regs.gpr[2];
|
|
|
|
else if (!_stricmp(name, "cr")) return &Core->regs.cr;
|
|
else if (!_stricmp(name, "fpscr")) return &Core->regs.fpscr;
|
|
else if (!_stricmp(name, "xer")) return &Core->regs.spr[(int)Gekko::SPR::XER];
|
|
else if (!_stricmp(name, "lr")) return &Core->regs.spr[(int)Gekko::SPR::LR];
|
|
else if (!_stricmp(name, "ctr")) return &Core->regs.spr[(int)Gekko::SPR::CTR];
|
|
else if (!_stricmp(name, "msr")) return &Core->regs.msr;
|
|
|
|
else if (!_stricmp(name, "sr0")) return &Core->regs.sr[0];
|
|
else if (!_stricmp(name, "sr1")) return &Core->regs.sr[1];
|
|
else if (!_stricmp(name, "sr2")) return &Core->regs.sr[2];
|
|
else if (!_stricmp(name, "sr3")) return &Core->regs.sr[3];
|
|
else if (!_stricmp(name, "sr4")) return &Core->regs.sr[4];
|
|
else if (!_stricmp(name, "sr5")) return &Core->regs.sr[5];
|
|
else if (!_stricmp(name, "sr6")) return &Core->regs.sr[6];
|
|
else if (!_stricmp(name, "sr7")) return &Core->regs.sr[7];
|
|
else if (!_stricmp(name, "sr8")) return &Core->regs.sr[8];
|
|
else if (!_stricmp(name, "sr9")) return &Core->regs.sr[9];
|
|
else if (!_stricmp(name, "sr10")) return &Core->regs.sr[10];
|
|
else if (!_stricmp(name, "sr11")) return &Core->regs.sr[11];
|
|
else if (!_stricmp(name, "sr12")) return &Core->regs.sr[12];
|
|
else if (!_stricmp(name, "sr13")) return &Core->regs.sr[13];
|
|
else if (!_stricmp(name, "sr14")) return &Core->regs.sr[14];
|
|
else if (!_stricmp(name, "sr15")) return &Core->regs.sr[15];
|
|
|
|
else if (!_stricmp(name, "ibat0u")) return &Core->regs.spr[(int)Gekko::SPR::IBAT0U];
|
|
else if (!_stricmp(name, "ibat1u")) return &Core->regs.spr[(int)Gekko::SPR::IBAT1U];
|
|
else if (!_stricmp(name, "ibat2u")) return &Core->regs.spr[(int)Gekko::SPR::IBAT2U];
|
|
else if (!_stricmp(name, "ibat3u")) return &Core->regs.spr[(int)Gekko::SPR::IBAT3U];
|
|
else if (!_stricmp(name, "ibat0l")) return &Core->regs.spr[(int)Gekko::SPR::IBAT0L];
|
|
else if (!_stricmp(name, "ibat1l")) return &Core->regs.spr[(int)Gekko::SPR::IBAT1L];
|
|
else if (!_stricmp(name, "ibat2l")) return &Core->regs.spr[(int)Gekko::SPR::IBAT2L];
|
|
else if (!_stricmp(name, "ibat3l")) return &Core->regs.spr[(int)Gekko::SPR::IBAT3L];
|
|
else if (!_stricmp(name, "dbat0u")) return &Core->regs.spr[(int)Gekko::SPR::DBAT0U];
|
|
else if (!_stricmp(name, "dbat1u")) return &Core->regs.spr[(int)Gekko::SPR::DBAT1U];
|
|
else if (!_stricmp(name, "dbat2u")) return &Core->regs.spr[(int)Gekko::SPR::DBAT2U];
|
|
else if (!_stricmp(name, "dbat3u")) return &Core->regs.spr[(int)Gekko::SPR::DBAT3U];
|
|
else if (!_stricmp(name, "dbat0l")) return &Core->regs.spr[(int)Gekko::SPR::DBAT0L];
|
|
else if (!_stricmp(name, "dbat1l")) return &Core->regs.spr[(int)Gekko::SPR::DBAT1L];
|
|
else if (!_stricmp(name, "dbat2l")) return &Core->regs.spr[(int)Gekko::SPR::DBAT2L];
|
|
else if (!_stricmp(name, "dbat3l")) return &Core->regs.spr[(int)Gekko::SPR::DBAT3L];
|
|
|
|
else if (!_stricmp(name, "sdr1")) return &Core->regs.spr[(int)Gekko::SPR::SDR1];
|
|
else if (!_stricmp(name, "sprg0")) return &Core->regs.spr[(int)Gekko::SPR::SPRG0];
|
|
else if (!_stricmp(name, "sprg1")) return &Core->regs.spr[(int)Gekko::SPR::SPRG1];
|
|
else if (!_stricmp(name, "sprg2")) return &Core->regs.spr[(int)Gekko::SPR::SPRG2];
|
|
else if (!_stricmp(name, "sprg3")) return &Core->regs.spr[(int)Gekko::SPR::SPRG3];
|
|
else if (!_stricmp(name, "dar")) return &Core->regs.spr[(int)Gekko::SPR::DAR];
|
|
else if (!_stricmp(name, "dsisr")) return &Core->regs.spr[(int)Gekko::SPR::DSISR];
|
|
else if (!_stricmp(name, "srr0")) return &Core->regs.spr[(int)Gekko::SPR::SRR0];
|
|
else if (!_stricmp(name, "srr1")) return &Core->regs.spr[(int)Gekko::SPR::SRR1];
|
|
else if (!_stricmp(name, "pmc1")) return &Core->regs.spr[953];
|
|
else if (!_stricmp(name, "pmc2")) return &Core->regs.spr[954];
|
|
else if (!_stricmp(name, "pmc3")) return &Core->regs.spr[957];
|
|
else if (!_stricmp(name, "pmc4")) return &Core->regs.spr[958];
|
|
else if (!_stricmp(name, "mmcr0")) return &Core->regs.spr[952];
|
|
else if (!_stricmp(name, "mmcr1")) return &Core->regs.spr[956];
|
|
else if (!_stricmp(name, "sia")) return &Core->regs.spr[955];
|
|
else if (!_stricmp(name, "sda")) return &Core->regs.spr[959];
|
|
|
|
else if (!_stricmp(name, "gqr0")) return &Core->regs.spr[(int)Gekko::SPR::GQR0];
|
|
else if (!_stricmp(name, "gqr1")) return &Core->regs.spr[(int)Gekko::SPR::GQR1];
|
|
else if (!_stricmp(name, "gqr2")) return &Core->regs.spr[(int)Gekko::SPR::GQR2];
|
|
else if (!_stricmp(name, "gqr3")) return &Core->regs.spr[(int)Gekko::SPR::GQR3];
|
|
else if (!_stricmp(name, "gqr4")) return &Core->regs.spr[(int)Gekko::SPR::GQR4];
|
|
else if (!_stricmp(name, "gqr5")) return &Core->regs.spr[(int)Gekko::SPR::GQR5];
|
|
else if (!_stricmp(name, "gqr6")) return &Core->regs.spr[(int)Gekko::SPR::GQR6];
|
|
else if (!_stricmp(name, "gqr7")) return &Core->regs.spr[(int)Gekko::SPR::GQR7];
|
|
|
|
else if (!_stricmp(name, "hid0")) return &Core->regs.spr[(int)Gekko::SPR::HID0];
|
|
else if (!_stricmp(name, "hid1")) return &Core->regs.spr[(int)Gekko::SPR::HID1];
|
|
else if (!_stricmp(name, "hid2")) return &Core->regs.spr[(int)Gekko::SPR::HID2];
|
|
|
|
else if (!_stricmp(name, "dabr")) return &Core->regs.spr[(int)Gekko::SPR::DABR];
|
|
else if (!_stricmp(name, "iabr")) return &Core->regs.spr[(int)Gekko::SPR::IABR];
|
|
else if (!_stricmp(name, "wpar")) return &Core->regs.spr[(int)Gekko::SPR::WPAR];
|
|
else if (!_stricmp(name, "l2cr")) return &Core->regs.spr[1017];
|
|
else if (!_stricmp(name, "dmau")) return &Core->regs.spr[(int)Gekko::SPR::DMAU];
|
|
else if (!_stricmp(name, "dmal")) return &Core->regs.spr[(int)Gekko::SPR::DMAL];
|
|
else if (!_stricmp(name, "thrm1")) return &Core->regs.spr[1020];
|
|
else if (!_stricmp(name, "thrm2")) return &Core->regs.spr[1021];
|
|
else if (!_stricmp(name, "thrm3")) return &Core->regs.spr[1022];
|
|
else if (!_stricmp(name, "ictc")) return &Core->regs.spr[1019];
|
|
|
|
else if (!_stricmp(name, "pc")) return &Core->regs.pc; // Wow !
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// Operations.
|
|
static uint32_t op_replace(uint32_t a, uint32_t b) { return b; }
|
|
static uint32_t op_add(uint32_t a, uint32_t b) { return a + b; }
|
|
static uint32_t op_sub(uint32_t a, uint32_t b) { return a - b; }
|
|
static uint32_t op_mul(uint32_t a, uint32_t b) { return a * b; }
|
|
static uint32_t op_div(uint32_t a, uint32_t b) { return b ? (a / b) : 0; }
|
|
static uint32_t op_or(uint32_t a, uint32_t b) { return a | b; }
|
|
static uint32_t op_and(uint32_t a, uint32_t b) { return a & b; }
|
|
static uint32_t op_xor(uint32_t a, uint32_t b) { return a ^ b; }
|
|
static uint32_t op_shl(uint32_t a, uint32_t b) { return a << b; }
|
|
static uint32_t op_shr(uint32_t a, uint32_t b) { return a >> b; }
|
|
|
|
// Special handling for MSR register.
|
|
static void describe_msr(uint32_t msr_val)
|
|
{
|
|
static const char* fpmod[4] =
|
|
{
|
|
"exceptions disabled",
|
|
"imprecise nonrecoverable",
|
|
"imprecise recoverable",
|
|
"precise mode",
|
|
};
|
|
int f, fe[2];
|
|
|
|
Report(Channel::Norm, "MSR: 0x%08X\n", msr_val);
|
|
|
|
if (msr_val & MSR_POW) Report(Channel::Norm, "MSR[POW]: 1, power management enabled\n");
|
|
else Report(Channel::Norm, "MSR[POW]: 0, power management disabled\n");
|
|
if (msr_val & MSR_ILE) Report(Channel::Norm, "MSR[ILE]: 1\n");
|
|
else Report(Channel::Norm, "MSR[ILE]: 0\n");
|
|
if (msr_val & MSR_EE) Report(Channel::Norm, "MSR[EE] : 1, external interrupts and decrementer exception are enabled\n");
|
|
else Report(Channel::Norm, "MSR[EE] : 0, external interrupts and decrementer exception are disabled\n");
|
|
if (msr_val & MSR_PR) Report(Channel::Norm, "MSR[PR] : 1, processor execute in user mode (UISA)\n");
|
|
else Report(Channel::Norm, "MSR[PR] : 0, processor execute in supervisor mode (OEA)\n");
|
|
if (msr_val & MSR_FP) Report(Channel::Norm, "MSR[FP] : 1, floating-point is available\n");
|
|
else Report(Channel::Norm, "MSR[FP] : 0, floating-point unavailable\n");
|
|
if (msr_val & MSR_ME) Report(Channel::Norm, "MSR[ME] : 1, machine check exceptions are enabled\n");
|
|
else Report(Channel::Norm, "MSR[ME] : 0, machine check exceptions are disabled\n");
|
|
|
|
fe[0] = msr_val & MSR_FE0 ? 1 : 0;
|
|
fe[1] = msr_val & MSR_FE1 ? 1 : 0;
|
|
f = (fe[0] << 1) | (fe[1]);
|
|
Report(Channel::Norm, "MSR[FE] : %i, floating-point %s\n", f, fpmod[f]);
|
|
|
|
if (msr_val & MSR_SE) Report(Channel::Norm, "MSR[SE] : 1, single-step tracing is enabled\n");
|
|
else Report(Channel::Norm, "MSR[SE] : 0, single-step tracing is disabled\n");
|
|
if (msr_val & MSR_BE) Report(Channel::Norm, "MSR[BE] : 1, branch tracing is enabled\n");
|
|
else Report(Channel::Norm, "MSR[BE] : 0, branch tracing is disabled\n");
|
|
if (msr_val & MSR_IP) Report(Channel::Norm, "MSR[IP] : 1, exception prefix to physical address is 0xFFFn_nnnn\n");
|
|
else Report(Channel::Norm, "MSR[IP] : 0, exception prefix to physical address is 0x000n_nnnn\n");
|
|
if (msr_val & MSR_IR) Report(Channel::Norm, "MSR[IR] : 1, instruction address translation is enabled\n");
|
|
else Report(Channel::Norm, "MSR[IR] : 0, instruction address translation is disabled\n");
|
|
if (msr_val & MSR_DR) Report(Channel::Norm, "MSR[DR] : 1, data address translation is enabled\n");
|
|
else Report(Channel::Norm, "MSR[DR] : 0, data address translation is disabled\n");
|
|
if (msr_val & MSR_PM) Report(Channel::Norm, "MSR[PM] : 1, performance monitoring is enabled for this thread\n");
|
|
else Report(Channel::Norm, "MSR[PM] : 0, performance monitoring is disabled for this thread\n");
|
|
if (msr_val & MSR_RI) Report(Channel::Norm, "MSR[RI] : 1\n");
|
|
else Report(Channel::Norm, "MSR[RI] : 0\n");
|
|
if (msr_val & MSR_LE) Report(Channel::Norm, "MSR[LE] : 1, processor runs in little-endian mode\n");
|
|
else Report(Channel::Norm, "MSR[LE] : 0, processor runs in big-endian mode\n");
|
|
}
|
|
|
|
// HID0 info
|
|
static void describe_hid0(uint32_t val)
|
|
{
|
|
Report(Channel::Norm, "HID0: 0x%08X\n", val);
|
|
|
|
if (val & HID0_EMCP) Report(Channel::Norm, "HID0[EMCP] : 1, Asserting MCP causes checkstop or a machine check\n");
|
|
else Report(Channel::Norm, "HID0[EMCP] : 0, Masks MCP. Asserting MCP does not generate a machine check exception or a checkstop\n");
|
|
if (val & HID0_DBP) Report(Channel::Norm, "HID0[DBP] : 1, Disable parity generation\n");
|
|
else Report(Channel::Norm, "HID0[DBP] : 0, Parity generation is enabled\n");
|
|
if (val & HID0_EBA) Report(Channel::Norm, "HID0[EBA] : 1, Allows a address parity error to cause a checkstop or a machine check\n");
|
|
else Report(Channel::Norm, "HID0[EBA] : 0, Prevents address parity checking\n");
|
|
if (val & HID0_EBD) Report(Channel::Norm, "HID0[EBD] : 1, Allows a data parity error to cause a checkstop or machine check\n");
|
|
else Report(Channel::Norm, "HID0[EBD] : 0, Parity checking is disabled\n");
|
|
if (val & HID0_PAR) Report(Channel::Norm, "HID0[PAR] : 1, Alters bus protocol slightly by preventing the processor from driving ARTRY to high\n");
|
|
else Report(Channel::Norm, "HID0[PAR] : 0, Precharge of ARTRY enabled\n");
|
|
if (val & HID0_DOZE) Report(Channel::Norm, "HID0[DOZE] : 1, Doze mode enabled\n");
|
|
else Report(Channel::Norm, "HID0[DOZE] : 0, Doze mode disabled\n");
|
|
if (val & HID0_NAP) Report(Channel::Norm, "HID0[NAP] : 1, Nap mode enabled\n");
|
|
else Report(Channel::Norm, "HID0[NAP] : 0, Nap mode disabled\n");
|
|
if (val & HID0_SLEEP) Report(Channel::Norm, "HID0[SLEEP]: 1, Sleep mode enabled\n");
|
|
else Report(Channel::Norm, "HID0[SLEEP]: 0, Sleep mode disabled\n");
|
|
if (val & HID0_DPM) Report(Channel::Norm, "HID0[DPM] : 1, Dynamic power management is enabled\n");
|
|
else Report(Channel::Norm, "HID0[DPM] : 0, Dynamic power management is disabled\n");
|
|
if (val & HID0_NHR) Report(Channel::Norm, "HID0[NHR] : 1, Hard reset has not occurred\n");
|
|
else Report(Channel::Norm, "HID0[NHR] : 0, Hard reset occurred\n");
|
|
if (val & HID0_ICE) Report(Channel::Norm, "HID0[ICE] : 1, Instruction cache is enabled\n");
|
|
else Report(Channel::Norm, "HID0[ICE] : 0, Instruction cache is disabled\n");
|
|
if (val & HID0_DCE) Report(Channel::Norm, "HID0[DCE] : 1, Data cache is enabled\n");
|
|
else Report(Channel::Norm, "HID0[DCE] : 0, Data cache is disabled\n");
|
|
if (val & HID0_ILOCK) Report(Channel::Norm, "HID0[ILOCK]: 1, Instruction cache locked (frozen)\n");
|
|
else Report(Channel::Norm, "HID0[ILOCK]: 0, Instruction cache not locked\n");
|
|
if (val & HID0_DLOCK) Report(Channel::Norm, "HID0[DLOCK]: 1, Data cache locked (frozen)\n");
|
|
else Report(Channel::Norm, "HID0[DLOCK]: 0, Data cache not locked\n");
|
|
if (val & HID0_ICFI) Report(Channel::Norm, "HID0[ICFI] : 1, Instruction cache invalidating\n");
|
|
else Report(Channel::Norm, "HID0[ICFI] : 0, Instruction cache is not invalidated\n");
|
|
if (val & HID0_DCFI) Report(Channel::Norm, "HID0[DCFI] : 1, Data cache invalidating\n");
|
|
else Report(Channel::Norm, "HID0[DCFI] : 0, Data cache is not invalidated\n");
|
|
if (val & HID0_SPD) Report(Channel::Norm, "HID0[SPD] : 1, Speculative bus accesses to nonguarded space disabled\n");
|
|
else Report(Channel::Norm, "HID0[SPD] : 0, Speculative bus accesses to nonguarded space enabled\n");
|
|
if (val & HID0_IFEM) Report(Channel::Norm, "HID0[IFEM] : 1, Instruction fetches reflect the M bit from the WIM settings\n");
|
|
else Report(Channel::Norm, "HID0[IFEM] : 0, Instruction fetches M bit disabled\n");
|
|
if (val & HID0_SGE) Report(Channel::Norm, "HID0[SGE] : 1, Store gathering is enabled\n");
|
|
else Report(Channel::Norm, "HID0[SGE] : 0, Store gathering is disabled \n");
|
|
if (val & HID0_DCFA) Report(Channel::Norm, "HID0[DCFA] : 1, Data cache flush assist facility is enabled\n");
|
|
else Report(Channel::Norm, "HID0[DCFA] : 0, Data cache flush assist facility is disabled\n");
|
|
if (val & HID0_BTIC) Report(Channel::Norm, "HID0[BTIC] : 1, BTIC is enabled\n");
|
|
else Report(Channel::Norm, "HID0[BTIC] : 0, BTIC is disabled\n");
|
|
if (val & HID0_ABE) Report(Channel::Norm, "HID0[ABE] : 1, Address-only operations are broadcast on the 60x bus\n");
|
|
else Report(Channel::Norm, "HID0[ABE] : 0, Address-only operations affect only local L1 and L2 caches and are not broadcast\n");
|
|
if (val & HID0_BHT) Report(Channel::Norm, "HID0[BHT] : 1, Branch history enabled\n");
|
|
else Report(Channel::Norm, "HID0[BHT] : 0, Branch history disabled\n");
|
|
if (val & HID0_NOOPTI) Report(Channel::Norm, "HID0[NOOPTI]: 1, The dcbt and dcbtst instructions are no-oped globally\n");
|
|
else Report(Channel::Norm, "HID0[NOOPTI]: 0, The dcbt and dcbtst instructions are enabled\n");
|
|
}
|
|
|
|
static Json::Value* CmdGetSetReg(std::vector<std::string>& args)
|
|
{
|
|
uint32_t(*op)(uint32_t a, uint32_t b) = NULL;
|
|
|
|
uint32_t* n = getreg(args[1].c_str());
|
|
if (n == NULL)
|
|
{
|
|
Report(Channel::Norm, "unknown register : %s\n", args[1].c_str());
|
|
return nullptr;
|
|
}
|
|
|
|
// show register
|
|
if (args.size() <= 3)
|
|
{
|
|
if (!_stricmp(args[1].c_str(), "msr")) describe_msr(*n);
|
|
else if (!_stricmp(args[1].c_str(), "hid0")) describe_hid0(*n);
|
|
else Report(Channel::Norm, "%s = %i (0x%X)\n", args[1].c_str(), *n, *n);
|
|
return nullptr;
|
|
}
|
|
|
|
// Get operation.
|
|
if (!strcmp(args[2].c_str(), "=")) op = op_replace;
|
|
else if (!strcmp(args[2].c_str(), "+")) op = op_add;
|
|
else if (!strcmp(args[2].c_str(), "-")) op = op_sub;
|
|
else if (!strcmp(args[2].c_str(), "*")) op = op_mul;
|
|
else if (!strcmp(args[2].c_str(), "/")) op = op_div;
|
|
else if (!strcmp(args[2].c_str(), "|")) op = op_or;
|
|
else if (!strcmp(args[2].c_str(), "&")) op = op_and;
|
|
else if (!strcmp(args[2].c_str(), "^")) op = op_xor;
|
|
else if (!strcmp(args[2].c_str(), "<<")) op = op_shl;
|
|
else if (!strcmp(args[2].c_str(), ">>")) op = op_shr;
|
|
if (op == NULL)
|
|
{
|
|
Report(Channel::Norm, "Unknown operation: %s\n", args[2].c_str());
|
|
return nullptr;
|
|
}
|
|
|
|
// New value
|
|
uint32_t* m = getreg(args[3].c_str());
|
|
if (m == NULL)
|
|
{
|
|
int i = strtoul(args[3].c_str(), NULL, 0);
|
|
Report(Channel::Norm, "%s %s %i (0x%X)\n", args[1].c_str(), args[2].c_str(), i, i);
|
|
*n = op(*n, i);
|
|
}
|
|
else
|
|
{
|
|
Report(Channel::Norm, "%s %s %s\n", args[1].c_str(), args[2].c_str(), args[3].c_str());
|
|
*n = op(*n, *m);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdBreakExec(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
Core->AddBreakpoint(addr);
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdBreakRead(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
Core->AddReadBreak(addr);
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdBreakWrite(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
Core->AddWriteBreak(addr);
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdBreakClearAll(std::vector<std::string>& args)
|
|
{
|
|
Core->ClearBreakpoints();
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdCacheLog(std::vector<std::string>& args)
|
|
{
|
|
Gekko::CacheLogLevel level = (Gekko::CacheLogLevel)atoi(args[1].c_str());
|
|
Core->cache->SetLogLevel(level);
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdIsRunning(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Bool;
|
|
|
|
output->value.AsBool = Core->IsRunning();
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoRun(std::vector<std::string>& args)
|
|
{
|
|
Core->Run();
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoSuspend(std::vector<std::string>& args)
|
|
{
|
|
Core->Suspend();
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoStep(std::vector<std::string>& args)
|
|
{
|
|
if (!Core->IsRunning())
|
|
{
|
|
Core->Step();
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoSkipInstruction(std::vector<std::string>& args)
|
|
{
|
|
if (!Core->IsRunning())
|
|
{
|
|
Report(Channel::CPU, "Skipped instruction at: 0x%08X!\n", Core->regs.pc);
|
|
Core->regs.pc += 4;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdGetGpr(std::vector<std::string>& args)
|
|
{
|
|
int n = atoi(args[1].c_str());
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = Core->regs.gpr[n];
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetPs0(std::vector<std::string>& args)
|
|
{
|
|
int n = atoi(args[1].c_str());
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = Core->regs.fpr[n].uval;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetPs1(std::vector<std::string>& args)
|
|
{
|
|
int n = atoi(args[1].c_str());
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = Core->regs.ps1[n].uval;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetPc(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = Core->regs.pc;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetMsr(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = Core->regs.msr;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetCr(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = Core->regs.cr;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetFpscr(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = Core->regs.fpscr;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetSpr(std::vector<std::string>& args)
|
|
{
|
|
int n = atoi(args[1].c_str());
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = Core->regs.spr[n];
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetSr(std::vector<std::string>& args)
|
|
{
|
|
int n = atoi(args[1].c_str());
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = Core->regs.sr[n];
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetTbu(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = Core->regs.tb.Part.u;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGetTbl(std::vector<std::string>& args)
|
|
{
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = Core->regs.tb.Part.l;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdTranslateDMmu(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
uint32_t pa = Gekko::BadAddress;
|
|
|
|
if (JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
int WIMG;
|
|
pa = Core->EffectiveToPhysical(addr, Gekko::MmuAccess::Read, WIMG);
|
|
}
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = (uint64_t)MITranslatePhysicalAddress(pa, sizeof(uint32_t));
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdTranslateIMmu(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
uint32_t pa = Gekko::BadAddress;
|
|
|
|
if (JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
int WIMG;
|
|
pa = Core->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG);
|
|
}
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsInt = (uint64_t)MITranslatePhysicalAddress(pa, sizeof(uint32_t));
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdVirtualToPhysicalDMmu(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
uint32_t pa = Gekko::BadAddress;
|
|
|
|
if (JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
int WIMG;
|
|
pa = Core->EffectiveToPhysical(addr, Gekko::MmuAccess::Read, WIMG);
|
|
}
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = pa;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdVirtualToPhysicalIMmu(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
uint32_t pa = Gekko::BadAddress;
|
|
|
|
if (JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
int WIMG;
|
|
pa = Core->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG);
|
|
}
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Int;
|
|
|
|
output->value.AsUint32 = pa;
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoTestBreakpoint(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Bool;
|
|
|
|
output->value.AsBool = Core->IsBreakpoint(addr);
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoToggleBreakpoint(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
Core->ToggleBreakpoint(addr);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoAddOneShotBreakpoint(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
Core->AddOneShotBreakpoint(addr);
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// Disassemble instruction at Gekko virtual memory address
|
|
static Json::Value* CmdGekkoDisasm(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
uint32_t pa = Gekko::BadAddress;
|
|
|
|
if (JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
int WIMG;
|
|
pa = Core->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG);
|
|
}
|
|
|
|
std::string text = "";
|
|
|
|
uint8_t* ptr = MITranslatePhysicalAddress(pa, sizeof(uint32_t));
|
|
|
|
if (ptr != nullptr)
|
|
{
|
|
Gekko::DecoderInfo info = { 0 };
|
|
|
|
uint32_t instr = _BYTESWAP_UINT32(*(uint32_t*)ptr);
|
|
|
|
Gekko::Decoder::Decode(addr, instr, &info);
|
|
|
|
text = Gekko::GekkoDisasm::Disasm(addr, &info, false, false);
|
|
}
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Array;
|
|
|
|
output->AddAnsiString(nullptr, text.c_str());
|
|
|
|
return output;
|
|
}
|
|
|
|
// Disassemble the instruction without accessing memory (all necessary information is passed through parameters)
|
|
static Json::Value* CmdGekkoDisasmNoMemAccess(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
uint32_t instr = strtoul(args[2].c_str(), nullptr, 0);
|
|
bool showAddress = strtoul(args[3].c_str(), nullptr, 0) != 0;
|
|
bool showBytes = strtoul(args[4].c_str(), nullptr, 0) != 0;
|
|
|
|
Gekko::DecoderInfo info = { 0 };
|
|
Gekko::Decoder::Decode(addr, instr, &info);
|
|
|
|
std::string text = Gekko::GekkoDisasm::Disasm(addr, &info, showAddress, showBytes);
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Array;
|
|
|
|
output->AddAnsiString(nullptr, text.c_str());
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdGekkoIsBranch(std::vector<std::string>& args)
|
|
{
|
|
uint32_t addr = strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
uint32_t pa = Gekko::BadAddress;
|
|
|
|
if (JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
int WIMG;
|
|
pa = Core->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG);
|
|
}
|
|
|
|
bool flowControl = false;
|
|
uint32_t targetAddress = 0;
|
|
|
|
if (pa < RAMSIZE)
|
|
{
|
|
Gekko::DecoderInfo info = { 0 };
|
|
|
|
uint8_t* ptr = &mi.ram[pa];
|
|
uint32_t instr = _BYTESWAP_UINT32(*(uint32_t*)ptr);
|
|
|
|
Gekko::Decoder::Decode(addr, instr, &info);
|
|
|
|
flowControl = info.flow;
|
|
targetAddress = info.Imm.Address;
|
|
}
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Array;
|
|
|
|
output->AddBool(nullptr, flowControl);
|
|
output->AddUInt32(nullptr, targetAddress);
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdNop(std::vector<std::string>& args)
|
|
{
|
|
if (!JDI::Hub.ExecuteFastBool("IsLoaded"))
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
uint32_t ea = strtoul(args[1].c_str(), nullptr, 0);
|
|
Core->WriteWord(ea, 0x6000'0000);
|
|
|
|
// Refresh physical memory (MEM) storage
|
|
int wimg;
|
|
uint32_t pa = Core->EffectiveToPhysical(ea, Gekko::MmuAccess::Read , wimg);
|
|
if (pa != Gekko::BadAddress) {
|
|
PIWriteWord(pa, 0x6000'0000);
|
|
}
|
|
|
|
// You also need to invalidate the Gekko instruction cache
|
|
Core->icache->Invalidate(pa);
|
|
|
|
// Refresh the debugger contents
|
|
if (debugger != nullptr) {
|
|
debugger->InvalidateAll();
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// Enables or disables the maintenance of opcode usage statistics
|
|
static Json::Value* CmdEnableOpcodeStats(std::vector<std::string>& args)
|
|
{
|
|
bool enable = strtoul(args[1].c_str(), nullptr, 0) != 0 ? true : false;
|
|
Core->EnableOpcodeStats(enable);
|
|
return nullptr;
|
|
}
|
|
|
|
// Displays the most commonly used Gekko opcodes
|
|
static Json::Value* CmdPrintOpcodeStats(std::vector<std::string>& args)
|
|
{
|
|
size_t maxCount = strtoul(args[1].c_str(), nullptr, 0);
|
|
Core->PrintOpcodeStats(maxCount);
|
|
return nullptr;
|
|
}
|
|
|
|
// Clears statistics of opcode usage
|
|
static Json::Value* CmdResetOpcodeStats(std::vector<std::string>& args)
|
|
{
|
|
Core->ResetOpcodeStats();
|
|
return nullptr;
|
|
}
|
|
|
|
// Runs a low priority thread that prints opcode statistics once a second
|
|
static Json::Value* CmdRunOpcodeStats(std::vector<std::string>& args)
|
|
{
|
|
Core->RunOpcodeStatsThread();
|
|
return nullptr;
|
|
}
|
|
|
|
// Stop the thread that outputs the opcode statistics
|
|
static Json::Value* CmdStopOpcodeStats(std::vector<std::string>& args)
|
|
{
|
|
Core->StopOpcodeStatsThread();
|
|
return nullptr;
|
|
}
|
|
|
|
// Parse Gekko instruction
|
|
static Json::Value* CmdGekkoAnalyze(std::vector<std::string>& args)
|
|
{
|
|
uint32_t pc = strtoul(args[1].c_str(), nullptr, 0);
|
|
uint32_t opcode = strtoul(args[2].c_str(), nullptr, 0);
|
|
|
|
Gekko::DecoderInfo info = { 0 };
|
|
|
|
Gekko::Decoder::Decode(pc, opcode, &info);
|
|
|
|
// Array: [Int instr, Int numParams, Int param0, Int paramBits0, Int param1, Int paramBits1, Int param2, Int paramBits2, Int param3, Int paramBits3, Int param4, Int paramBits4, UInt32 immedValue, UInt32 newPc, Bool flow]
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Array;
|
|
|
|
output->AddInt(nullptr, (int)info.instr);
|
|
output->AddInt(nullptr, (int)info.numParam);
|
|
|
|
uint32_t imm = 0;
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
if (i >= info.numParam)
|
|
{
|
|
output->AddInt(nullptr, (int)Gekko::Param::Unknown);
|
|
output->AddInt(nullptr, 0);
|
|
continue;
|
|
}
|
|
|
|
// Immediate parameter values are stored in a separate field.
|
|
|
|
switch (info.param[i])
|
|
{
|
|
case Gekko::Param::Simm:
|
|
imm = (uint32_t)(int32_t)info.Imm.Signed;
|
|
break;
|
|
case Gekko::Param::Uimm:
|
|
imm = (uint32_t)info.Imm.Unsigned;
|
|
break;
|
|
case Gekko::Param::Address:
|
|
imm = info.Imm.Address;
|
|
break;
|
|
}
|
|
|
|
output->AddInt(nullptr, (int)info.param[i]);
|
|
output->AddInt(nullptr, (int)info.paramBits[i]); // Doesn't make sense for Immediate parameters, but remains for conformity.
|
|
}
|
|
|
|
output->AddUInt32(nullptr, imm); // If the Immediate parameter is missing, it is 0
|
|
output->AddUInt32(nullptr, info.pc);
|
|
output->AddBool(nullptr, info.flow);
|
|
|
|
return output;
|
|
}
|
|
|
|
// Return the name of the Gekko instruction (Gekko::Instruction)
|
|
static Json::Value* CmdGekkoInstrToString(std::vector<std::string>& args)
|
|
{
|
|
Gekko::DecoderInfo info = { 0 };
|
|
info.instr = (Gekko::Instruction)strtoul(args[1].c_str(), nullptr, 0);
|
|
|
|
std::string instrName = Gekko::GekkoDisasm::InstrToString(&info);
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Array;
|
|
|
|
output->AddAnsiString(nullptr, instrName.c_str());
|
|
|
|
return output;
|
|
}
|
|
|
|
// Return the parameter name of a Gekko instruction (Gekko::Param)
|
|
static Json::Value* CmdGekkoInstrParamToString(std::vector<std::string>& args)
|
|
{
|
|
Gekko::DecoderInfo info = { 0 };
|
|
|
|
info.param[0] = (Gekko::Param)strtoul(args[1].c_str(), nullptr, 0);
|
|
info.paramBits[0] = strtoul(args[2].c_str(), nullptr, 0);
|
|
uint32_t imm = strtoul(args[3].c_str(), nullptr, 0);
|
|
|
|
// Immediate parameter values are stored in a separate field.
|
|
|
|
switch (info.param[0])
|
|
{
|
|
case Gekko::Param::Simm:
|
|
info.Imm.Signed = imm;
|
|
break;
|
|
case Gekko::Param::Uimm:
|
|
info.Imm.Unsigned = imm;
|
|
break;
|
|
case Gekko::Param::Address:
|
|
info.Imm.Address = imm;
|
|
break;
|
|
}
|
|
|
|
std::string paramName = Gekko::GekkoDisasm::ParamName(info.param[0]);
|
|
std::string paramText = Gekko::GekkoDisasm::ParamToString(info.param[0], info.paramBits[0], &info);
|
|
|
|
Json::Value* output = new Json::Value();
|
|
output->type = Json::ValueType::Array;
|
|
|
|
output->AddAnsiString(nullptr, paramName.c_str());
|
|
output->AddAnsiString(nullptr, paramText.c_str());
|
|
|
|
return output;
|
|
}
|
|
|
|
static Json::Value* CmdDumpDTLB(std::vector<std::string>& args)
|
|
{
|
|
Core->DumpDTLB();
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdDumpITLB(std::vector<std::string>& args)
|
|
{
|
|
Core->DumpITLB();
|
|
return nullptr;
|
|
}
|
|
|
|
static Json::Value* CmdInvalidateTLB(std::vector<std::string>& args)
|
|
{
|
|
Core->InvalidateTLBAll();
|
|
Report(Channel::CPU, "All TLB are invalidated\n");
|
|
return nullptr;
|
|
}
|
|
|
|
void gekko_init_handlers()
|
|
{
|
|
JDI::Hub.AddCmd("run", CmdRun);
|
|
JDI::Hub.AddCmd("stop", CmdStop);
|
|
JDI::Hub.AddCmd("r", CmdGetSetReg);
|
|
JDI::Hub.AddCmd("b", CmdBreakExec);
|
|
JDI::Hub.AddCmd("br", CmdBreakRead);
|
|
JDI::Hub.AddCmd("bw", CmdBreakWrite);
|
|
JDI::Hub.AddCmd("bc", CmdBreakClearAll);
|
|
JDI::Hub.AddCmd("CacheLog", CmdCacheLog);
|
|
|
|
JDI::Hub.AddCmd("IsRunning", CmdIsRunning);
|
|
JDI::Hub.AddCmd("GekkoRun", CmdGekkoRun);
|
|
JDI::Hub.AddCmd("GekkoSuspend", CmdGekkoSuspend);
|
|
JDI::Hub.AddCmd("GekkoStep", CmdGekkoStep);
|
|
JDI::Hub.AddCmd("GekkoSkipInstruction", CmdGekkoSkipInstruction);
|
|
|
|
JDI::Hub.AddCmd("GetGpr", CmdGetGpr);
|
|
JDI::Hub.AddCmd("GetPs0", CmdGetPs0);
|
|
JDI::Hub.AddCmd("GetPs1", CmdGetPs1);
|
|
JDI::Hub.AddCmd("GetPc", CmdGetPc);
|
|
JDI::Hub.AddCmd("GetMsr", CmdGetMsr);
|
|
JDI::Hub.AddCmd("GetCr", CmdGetCr);
|
|
JDI::Hub.AddCmd("GetFpscr", CmdGetFpscr);
|
|
JDI::Hub.AddCmd("GetSpr", CmdGetSpr);
|
|
JDI::Hub.AddCmd("GetSr", CmdGetSr);
|
|
JDI::Hub.AddCmd("GetTbu", CmdGetTbu);
|
|
JDI::Hub.AddCmd("GetTbl", CmdGetTbl);
|
|
|
|
JDI::Hub.AddCmd("TranslateDMmu", CmdTranslateDMmu);
|
|
JDI::Hub.AddCmd("TranslateIMmu", CmdTranslateIMmu);
|
|
JDI::Hub.AddCmd("VirtualToPhysicalDMmu", CmdVirtualToPhysicalDMmu);
|
|
JDI::Hub.AddCmd("VirtualToPhysicalIMmu", CmdVirtualToPhysicalIMmu);
|
|
|
|
JDI::Hub.AddCmd("GekkoTestBreakpoint", CmdGekkoTestBreakpoint);
|
|
JDI::Hub.AddCmd("GekkoToggleBreakpoint", CmdGekkoToggleBreakpoint);
|
|
JDI::Hub.AddCmd("GekkoAddOneShotBreakpoint", CmdGekkoAddOneShotBreakpoint);
|
|
|
|
JDI::Hub.AddCmd("GekkoDisasm", CmdGekkoDisasm);
|
|
JDI::Hub.AddCmd("GekkoDisasmNoMemAccess", CmdGekkoDisasmNoMemAccess);
|
|
JDI::Hub.AddCmd("GekkoIsBranch", CmdGekkoIsBranch);
|
|
|
|
JDI::Hub.AddCmd("nop", CmdNop);
|
|
|
|
JDI::Hub.AddCmd("EnableOpcodeStats", CmdEnableOpcodeStats);
|
|
JDI::Hub.AddCmd("PrintOpcodeStats", CmdPrintOpcodeStats);
|
|
JDI::Hub.AddCmd("ResetOpcodeStats", CmdResetOpcodeStats);
|
|
JDI::Hub.AddCmd("RunOpcodeStats", CmdRunOpcodeStats);
|
|
JDI::Hub.AddCmd("StopOpcodeStats", CmdStopOpcodeStats);
|
|
|
|
JDI::Hub.AddCmd("GekkoAnalyze", CmdGekkoAnalyze);
|
|
JDI::Hub.AddCmd("GekkoInstrToString", CmdGekkoInstrToString);
|
|
JDI::Hub.AddCmd("GekkoInstrParamToString", CmdGekkoInstrParamToString);
|
|
|
|
JDI::Hub.AddCmd("dtlb", CmdDumpDTLB);
|
|
JDI::Hub.AddCmd("itlb", CmdDumpITLB);
|
|
JDI::Hub.AddCmd("tlbinv", CmdInvalidateTLB);
|
|
}
|
|
}
|