⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm7tdmi.cpp

📁 一个任天堂掌上游戏机NDS的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
* 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(&reg, 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 + -