?? arm7tdmi.cpp
字號:
/**************************************************************************
* DSemu - The Next Generation *
* Portable ARM7TDMI core: Plugin implementation [arm7tdmi.cpp] *
* Copyright Imran Nazar, 2005; released under the BSD public licence. *
**************************************************************************/
#include <string>
#include <utility>
#include "arm7tdmi.h"
#include "armdasm.h"
#include "plgmmu32.h"
#include "plggui.h"
#include "datadefs.h"
#include "log.h"
#include "err.h"
#include "font5x7.h"
#ifdef ARM7TDMI_X86
# include "x86emit.h"
#endif
//---Static private class members------------------------------------------
// Every plugin has an INFO structure attached, with info about the plugin.
PLUGININFO ARM7TDMI::pInfo={
PLUGIN_TYPE_CPU,
0x00010001,
#ifdef ARM7TDMI_X86
"Dynamic binary translator: ARM7TDMI to x86",
#else
"Portable ARM7TDMI core",
#endif
"DSemu-ng"
};
ARM7TDMI::REGS ARM7TDMI::reg;
std::map<u32, int> ARM7TDMI::bkpts;
std::map<u32, CODEBLOCK> ARM7TDMI::blocks;
std::string ARM7TDMI::pluginName;
FILE *ARM7TDMI::dumpfile;
MMU32Plugin *ARM7TDMI::MMU=NULL;
GUIPlugin *ARM7TDMI::GUI=NULL;
u32 *ARM7TDMI::dbgbuffer = NULL;
int ARM7TDMI::dbgwinID = 0;
ARMDasm ARM7TDMI::dasm(rdWhelper);
const char *ARM7TDMI::modeStrings[7] = {
"USR", "FIQ", "IRQ", "SVC", "ABT", "UND", "SYS"
};
const int ARM7TDMI::modeToCpsrLUT[7] = {
CPSR_MUSR, CPSR_MFIQ, CPSR_MIRQ, CPSR_MSVC,
CPSR_MABT, CPSR_MUND, CPSR_MSYS
};
const int ARM7TDMI::modeFromCpsrLUT[16] = {
MODE_USR, MODE_FIQ, MODE_IRQ, MODE_SVC,
-1, -1, -1, MODE_ABT,
-1, -1, -1, MODE_UND,
-1, -1, -1, MODE_SYS,
};
//---Implementation--------------------------------------------------------
// The ARM7TDMI_DEBUG define masks the raw register dumper; when enabled,
// this will write all 16 registers and the CPSR to a file, in binary,
// every opcode. By default, this is off, because it's godawful slow.
// Initialise plugin
// Parameters: name - FQPN of plugin as listed in INI file
// req - Pointer to PluginRequest API function
// unreq - Pointer to PluginUnrequest API function
ARM7TDMI::ARM7TDMI(std::string name, REQPTR req, UNREQPTR unreq)
{
pName = std::string(name);
pClass = pName.substr(0, pName.find(".")+1);
pRequest = req;
pUnrequest = unreq;
pluginName = pName;
dbgbuffer = new u32[456*128];
if(!MMU) MMU = (MMU32Plugin*) pRequest(pClass+"mmu");
if(!GUI) GUI = (GUIPlugin*) pRequest("UI");
dbgwinID = GUI->subwinCreate(456, 128, "ARM7 debugger", dbgbuffer);
#ifdef ARM7TDMI_DEBUG
dumpfile = fopen("dsemu-trace.bin","wb");
#endif
MMU->setCPU(this);
// Simple check: Is this a 32-bit MMU? Our CPU's 32-bit after all
if((MMU->getCaps() & PLGMMU_CAPS_SIZEMASK) != PLGMMU_CAPS_32B)
{
pUnrequest(pClass+"mmu", 1); MMU = NULL;
throw Exception(ERR_CPU_INIT, pName,
pClass+"mmu isn't 32-bit.");
}
Logger::log(pName) << "Initialised.";
}
// Plugin cleanup
ARM7TDMI::~ARM7TDMI()
{
if(dbgbuffer) { delete dbgbuffer; dbgbuffer = NULL; }
pUnrequest("UI",0); GUI = NULL;
pUnrequest(pClass+"mmu", 1); MMU = NULL;
#ifdef ARM7TDMI_DEBUG
fclose(dumpfile);
#endif
Logger::log(pName) << "Shutdown after " << reg.clkcount << " cycles.";
}
// Reset CPU state
void ARM7TDMI::reset()
{
memset(®, 0, sizeof(REGS));
reg.curmode = MODE_SYS;
reg.cpsr = CPSR_MSYS;
MMU->reset();
memset(dbgbuffer, 0, 456*128*4);
status(3,0);
#ifdef ARM7TDMI_DEBUG
reg.r[15]+=4; fwrite(reg.r, 4, 17, dumpfile); reg.r[15]-=4;
#endif
Logger::log(pName) << "Reset.";
}
// Write to the debugger's framebuffer
void ARM7TDMI::status(int mode=3, int opt2=0)
{
char str[512]; int a; int xdim=456, ydim=128;
u32 r15=reg.r[15],r15orig=r15; static u32 r15old;
static u32 dbgoldr[16],rchanged[16];
static int dbgoldf[6],fchanged[6];
u32 op=0; u32 col; u16 oph=0;
int offset=0;
if(dbgbuffer)
{
Font5x7 prn(dbgbuffer, xdim, ydim);
cpsrUpdate();
if((mode==3 && reg.flags[FLAG_T]) || (mode==2))
r15-=(16-offset*2);
else
r15-=(32-offset*4);
for(a=0;a<16;a++)
{
if(r15==r15orig) col=0x00FF8080; else col=0x00FFFFFF;
if(bkpts.find(r15) != bkpts.end()) col=0x0000FFFF;
if((r15&0x0F000000)==(r15orig&0x0F000000)) op=MMU->rdW(r15);
switch(mode)
{
case 1:
if((r15&0x0F000000)==(r15orig&0x0F000000))
sprintf(str,"%08X: %08X | %s",r15,op,dasm.disasm(op,r15).c_str());
else sprintf(str,"%08X",r15);
r15+=4;
break;
case 2:
if((r15&0x0F000000)==(r15orig&0x0F000000))
{
if(r15&2) oph=op>>16; else oph=op&65535;
sprintf(str,"%08X: %04X | %s",r15,oph,dasm.tdisasm((u32)oph,r15).c_str());
}
else sprintf(str,"%08X",r15);
r15+=2; break;
case 3:
switch(reg.flags[FLAG_T])
{
case 0:
if((r15&0x0F000000)==(r15orig&0x0F000000))
sprintf(str,"%08X: %08X | %s",r15,op,dasm.disasm(op,r15).c_str());
else sprintf(str,"%08X",r15);
r15+=4; break;
case 1:
if((r15&0x0F000000)==(r15orig&0x0F000000))
{
if(r15&2) oph=op>>16; else oph=op&65535;
sprintf(str,"%08X: %04X | %s",r15,oph,dasm.tdisasm(oph,r15).c_str());
}
else sprintf(str,"%08X",r15);
r15+=2; break;
}
}
prn.print(str,0,a*8,col);
}
for(a=0;a<=15;a++)
{
sprintf(str,"r%02d: %08X",a,reg.r[a]);
if(r15old!=r15orig)
{
if(reg.r[a]!=dbgoldr[a]) { dbgoldr[a]=reg.r[a]; rchanged[a]=1; }
else rchanged[a]=0;
}
if(rchanged[a]) prn.print(str,56*6,a*8,0x000000FF);
else prn.print(str,56*6,a*8,0x00FFFFFF);
}
sprintf(str,"%s",modeStrings[reg.curmode]);
prn.print(str, 72*6, 56 ,0x00FFFFFF);
a=(reg.cpsr&CPSR_N)>>31; sprintf(str,"N: %d",a);
if(r15old!=r15orig)
if(a!=dbgoldf[0]) { dbgoldf[0]=a; fchanged[0]=1; } else fchanged[0]=0;
if(fchanged[0]) prn.print(str,72*6,0,0x000000FF);
else prn.print(str,72*6,0,0x00FFFFFF);
a=(reg.cpsr&CPSR_Z)>>30; sprintf(str,"Z: %d",a);
if(r15old!=r15orig)
if(a!=dbgoldf[1]) { dbgoldf[1]=a; fchanged[1]=1; } else fchanged[1]=0;
if(fchanged[1]) prn.print(str,72*6,8,0x000000FF);
else prn.print(str,72*6,8,0x00FFFFFF);
a=(reg.cpsr&CPSR_C)>>29; sprintf(str,"C: %d",a);
if(r15old!=r15orig)
if(a!=dbgoldf[2]) { dbgoldf[2]=a; fchanged[2]=1; } else fchanged[2]=0;
if(fchanged[2]) prn.print(str,72*6,16,0x000000FF);
else prn.print(str,72*6,16,0x00FFFFFF);
a=(reg.cpsr&CPSR_V)>>28; sprintf(str,"V: %d",a);
if(r15old!=r15orig)
if(a!=dbgoldf[3]) { dbgoldf[3]=a; fchanged[3]=1; } else fchanged[3]=0;
if(fchanged[3]) prn.print(str,72*6,24,0x000000FF);
else prn.print(str,72*6,24,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 ARM7TDMI::rdWhelper(u32 addr) { return MMU->rdW(addr); }
// Save registers, and switch processor modes
void ARM7TDMI::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 ARM7TDMI::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);
reg.cpsr &= ~CPSR_M;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -