📄 arm9es.cpp
字号:
else prn.print(str,72*6,32,0x00FFFFFF);
a=(reg.cpsr&CPSR_T)>>5; sprintf(str,"T: %d",a);
if(r15old!=r15orig)
if(a!=dbgoldf[5]) { dbgoldf[5]=a; fchanged[5]=1; } else fchanged[5]=0;
if(fchanged[5]) prn.print(str,72*6,40,0x000000FF);
else prn.print(str,72*6,40,0x00FFFFFF);
if(r15old!=r15orig) r15old=r15orig;
}
GUI->subwinRefresh(dbgwinID);
}
// Function the disassembler will use to read memory
u32 ARM9ES::rdWhelper(u32 addr) { return MMU->rdW(addr); }
// Save registers, and switch processor modes
void ARM9ES::modeSwitch(int in, int out)
{
//---Save state
reg.r0 = reg.r[0]; reg.r1 = reg.r[1];
reg.r2 = reg.r[2]; reg.r3 = reg.r[3];
reg.r4 = reg.r[4]; reg.r5 = reg.r[5];
reg.r6 = reg.r[6]; reg.r7 = reg.r[7];
if(in == MODE_FIQ)
{
reg.r8fiq = reg.r[8]; reg.r9fiq = reg.r[9];
reg.r10fiq = reg.r[10]; reg.r11fiq = reg.r[11];
reg.r12fiq = reg.r[12];
} else {
reg.r8 = reg.r[8]; reg.r9 = reg.r[9];
reg.r10 = reg.r[10]; reg.r11 = reg.r[11];
reg.r12 = reg.r[12];
}
switch(in)
{
case MODE_USR:
case MODE_SYS: reg.r13 = reg.r[13]; reg.r14 = reg.r[14]; break;
case MODE_IRQ: reg.r13irq = reg.r[13]; reg.r14irq = reg.r[14]; break;
case MODE_FIQ: reg.r13fiq = reg.r[13]; reg.r14fiq = reg.r[14]; break;
case MODE_SVC: reg.r13svc = reg.r[13]; reg.r14svc = reg.r[14]; break;
case MODE_ABT: reg.r13abt = reg.r[13]; reg.r14abt = reg.r[14]; break;
case MODE_UND: reg.r13und = reg.r[13]; reg.r14und = reg.r[14]; break;
}
reg.r15 = reg.r[15];
//---Switch to new mode
if(out == MODE_FIQ)
{
reg.r[8] = reg.r8fiq; reg.r[9] = reg.r9fiq;
reg.r[10] = reg.r10fiq; reg.r[11] = reg.r11fiq;
reg.r[12] = reg.r12fiq;
} else {
reg.r[8] = reg.r8; reg.r[9] = reg.r9;
reg.r[10] = reg.r10; reg.r[11] = reg.r11;
reg.r[12] = reg.r12;
}
switch(out)
{
case MODE_USR:
case MODE_SYS: reg.r[13] = reg.r13; reg.r[14] = reg.r14; break;
case MODE_IRQ: reg.r[13] = reg.r13irq; reg.r[14] = reg.r14irq; break;
case MODE_FIQ: reg.r[13] = reg.r13fiq; reg.r[14] = reg.r14fiq; break;
case MODE_SVC: reg.r[13] = reg.r13svc; reg.r[14] = reg.r14svc; break;
case MODE_ABT: reg.r[13] = reg.r13abt; reg.r[14] = reg.r14abt; break;
case MODE_UND: reg.r[13] = reg.r13und; reg.r[14] = reg.r14und; break;
}
reg.curmode = out;
cpsrUpdate();
}
// Update the CPSR based on the flags[] array
void ARM9ES::cpsrUpdate()
{
if(reg.flags[FLAG_N]) reg.cpsr|=CPSR_N; else reg.cpsr&=(~CPSR_N);
if(reg.flags[FLAG_Z]) reg.cpsr|=CPSR_Z; else reg.cpsr&=(~CPSR_Z);
if(reg.flags[FLAG_C]) reg.cpsr|=CPSR_C; else reg.cpsr&=(~CPSR_C);
if(reg.flags[FLAG_V]) reg.cpsr|=CPSR_V; else reg.cpsr&=(~CPSR_V);
if(reg.flags[FLAG_T]) reg.cpsr|=CPSR_T; else reg.cpsr&=(~CPSR_T);
if(reg.flags[FLAG_Q]) reg.cpsr|=CPSR_Q; else reg.cpsr&=(~CPSR_Q);
reg.cpsr &= ~CPSR_M;
reg.cpsr |= modeToCpsrLUT[reg.curmode];
}
// Split the CPSR into the flags[] array
void ARM9ES::cpsrSplit()
{
reg.flags[FLAG_N]=(reg.cpsr>>31)&1;
reg.flags[FLAG_Z]=(reg.cpsr>>30)&1;
reg.flags[FLAG_C]=(reg.cpsr>>29)&1;
reg.flags[FLAG_V]=(reg.cpsr>>28)&1;
reg.flags[FLAG_T]=(reg.cpsr>>5)&1;
reg.flags[FLAG_Q]=(reg.cpsr>>27)&1;
modeSwitch(reg.curmode, modeFromCpsrLUT[reg.cpsr&15]);
}
// Add to the internal clock
void ARM9ES::clockAdd(int cyc)
{
reg.clkcount += cyc;
}
// Toggle a breakpoint on or off at a specific address
void ARM9ES::dbgBkptToggle(u32 addr)
{
if(bkpts.find(addr) != bkpts.end()) bkpts.erase(addr);
else bkpts[addr]=1;
status();
}
// Return the map of breakpoint addresses to states
std::map<u32, int> ARM9ES::dbgBkptGet()
{
return bkpts;
}
// Work out how many bits in a 16-bit value are set to 1
// Used by the LDM/STM opcodes
// ACK: Donald Knuth (Sidesum algorithm)
int ARM9ES::ssum16(u16 val)
{
int res=val;
res=((res>>1)&0x5555)+(res&0x5555);
res=((res>>2)&0x3333)+(res&0x3333);
res=((res>>4)&0x0F0F)+(res&0x0F0F);
res=((res>>8)&0x00FF)+(res&0x00FF);
return res;
}
// Dispatch
// TODO: Optimise the dispatch loop, it's damned slow
int ARM9ES::exec(int cycles)
{
uint64_t stamp = reg.clkcount+cycles, start = reg.clkcount;
do {
if(bkpts.find(reg.r[15]) != bkpts.end())
{
switch(bkpts[reg.r[15]])
{
case 1:
bkpts[reg.r[15]]=2;
char str[20];
sprintf(str, "PC=%08X", reg.r[15]);
Logger::log(pName) << "Breakpoint encountered at " << str;
return -(reg.clkcount-start);
case 2:
bkpts[reg.r[15]]=1;
break;
}
}
if(reg.flags[FLAG_T])
{
reg.curop = (u32)MMU->rdH(reg.r[15]);
reg.r[15] += 2;
reg.clkcount += TLUT[(reg.curop&TMSK_OP)>>TSHFT_OP]();
#ifdef ARM9ES_DEBUG
cpsrUpdate();
reg.r[15]+=2; fwrite(reg.r, 4, 17, dumpfile); reg.r[15]-=2;
#endif
} else {
reg.curop = MMU->rdW(reg.r[15]);
//char str[64];
//sprintf(str, "%08X: %08X | ", reg.r[15], reg.curop);
//Logger::log(pluginName) << str << dasm.disasm(reg.curop);
reg.r[15] += 4;
if(condLUT[(reg.curop&MSK_COND)>>SHFT_COND]())
{
reg.clkcount += OLUT[((reg.curop&MSK_OP)>>SHFT_OPH)|
((reg.curop&MSK_FUNC)>>SHFT_FUNC)]();
}
else reg.clkcount++;
#ifdef ARM9ES_DEBUG
cpsrUpdate();
reg.r[15]+=4; fwrite(reg.r, 4, 17, dumpfile); reg.r[15]-=4;
#endif
}
} while(reg.clkcount < stamp);
return reg.clkcount - start;
}
// CPU is interrupted; set up the CPU state for the int handler
void ARM9ES::interrupt(int type)
{
// Type ignored for now, IRQ assumed
reg.flags[FLAG_T]=0;
cpsrUpdate();
reg.cpsr |= CPSR_I;
reg.r14irq = reg.r[15];
reg.spsr[MODE_IRQ] = reg.cpsr;
modeSwitch(reg.curmode, MODE_IRQ);
#ifdef ARM_HIGH_VECTORS
reg.r[15] = 0xFFFF0018;
#else
reg.r[15] = 0x00000018;
#endif
}
void ARM9ES::setPC(u32 pc)
{
reg.r[15] = pc;
}
//---Exceptional opcode handlers-------------------------------------------
// NOTE: As of right now, these do nothing; they are there such that the
// opcodes can safely call them if a problem occurs.
OPC opUND()
{
char str[80];
sprintf(str, " at %08X: %08X", reg.r[15], reg.curop);
//Logger::log(pluginName) << "Undefined opcode" << str;
return 1;
}
OPC opUNP()
{
char str[80];
sprintf(str, " at %08X: %08X", reg.r[15], reg.curop);
//Logger::log(pluginName) << "Unpredictable opcode" << str;
return 1;
}
OPC opUNI()
{
char str[80];
sprintf(str, " at %08X: %08X", reg.r[15], reg.curop);
//Logger::log(pluginName) << "Unimplemented opcode" << str;
return 1;
}
OPC opUNL()
{
// Would act as cache filler
return 1;
}
//---Plugin Support--------------------------------------------------------
// Retrieve Plugin class from outside
// Parameters: plg - Address of a pointer to a Plugin class to 'new'
// name - FQPN of plugin as listed in INI file
// req - Pointer to PluginRequest API function
// unreq - Pointer to PluginUnrequest API function
EXPORTFUNC void getPlugin(Plugin **plg,
std::string name,
REQPTR req, UNREQPTR unreq)
{
// Initialise a new Test plugin at the parameter
*plg = new ARM9ES(name, req, unreq);
}
// Provide plugin version information
PLUGININFO *ARM9ES::getinfo()
{
return &pInfo;
}
// Release plugin from outside
void ARM9ES::release()
{
// Delete the Test plugin that was 'new'd in getPlugin.
delete this;
}
/*** EOF: arm9es.cpp *****************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -