1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

- Implemented ARM9Interpreter & ARM9DisAsm.

- Implemented MemoryBlockLE & DynamicMemoryBlockLE.
- Implemented CPUDecoder.
This commit is contained in:
DH 2013-11-05 20:12:18 +02:00
parent 0b35be32a4
commit 6b22e7d90a
31 changed files with 475 additions and 177 deletions

View File

@ -0,0 +1,32 @@
#pragma once
#include "Emu/CPU/CPUDecoder.h"
#include "ARM9Opcodes.h"
class ARM9Decoder : public CPUDecoder
{
ARM9Opcodes& m_op;
public:
ARM9Decoder(ARM9Opcodes& op) : m_op(op)
{
}
virtual void DecodeMemory(const u64 address)
{
const u16 code0 = Memory.Read16(address);
const u16 code1 = Memory.Read16(address + 2);
const u16 opcode = code0;
switch(opcode)
{
case 0:
m_op.NULL_OP();
break;
default:
m_op.UNK(opcode, code0, code1);
break;
}
}
};

View File

@ -0,0 +1,36 @@
#pragma once
#include "Emu/ARM9/ARM9Opcodes.h"
#include "Emu/CPU/CPUDisAsm.h"
#include "Gui/DisAsmFrame.h"
#include "Emu/Memory/Memory.h"
class ARM9DisAsm
: public CPUDisAsm
, public ARM9Opcodes
{
public:
ARM9DisAsm(CPUDisAsmMode mode) : CPUDisAsm(mode)
{
}
protected:
virtual u32 DisAsmBranchTarget(const s32 imm)
{
return dump_pc + (imm << 2);
}
void NULL_OP()
{
Write("null");
}
void NOP()
{
Write("nop");
}
void UNK(const u16 opcode, const u16 code0, const u16 code1)
{
Write(wxString::Format("Unknown/Illegal opcode! (0x%04x : 0x%04x : 0x%04x)", opcode, code0, code1));
}
};

View File

@ -0,0 +1,29 @@
#pragma once
#include "Emu/ARM9/ARM9Opcodes.h"
class ARM9Interpreter : public ARM9Opcodes
{
ARM9Thread& CPU;
public:
ARM9Interpreter(ARM9Thread& cpu) : CPU(cpu)
{
}
protected:
void NULL_OP()
{
ConLog.Error("null");
Emu.Pause();
}
void NOP()
{
}
void UNK(const u16 opcode, const u16 code0, const u16 code1)
{
ConLog.Error("Unknown/Illegal opcode! (0x%04x : 0x%04x : 0x%04x)", opcode, code0, code1);
Emu.Pause();
}
};

View File

@ -0,0 +1,18 @@
#pragma once
namespace ARM9_opcodes
{
enum ARM9_MainOpcodes
{
};
}
class ARM9Opcodes
{
public:
virtual void NULL_OP() = 0;
virtual void NOP() = 0;
virtual void UNK(const u16 opcode, const u16 code0, const u16 code1) = 0;
};

View File

@ -1,5 +1,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "ARM9Thread.h" #include "ARM9Thread.h"
#include "ARM9Decoder.h"
#include "ARM9DisAsm.h"
#include "ARM9Interpreter.h"
ARM9Thread::ARM9Thread() : CPUThread(CPU_THREAD_ARM9) ARM9Thread::ARM9Thread() : CPUThread(CPU_THREAD_ARM9)
{ {
@ -50,6 +53,17 @@ void ARM9Thread::DoReset()
void ARM9Thread::DoRun() void ARM9Thread::DoRun()
{ {
switch(Ini.CPUDecoderMode.GetValue())
{
case 0:
//m_dec = new PPUDecoder(*new PPUDisAsm());
break;
case 1:
case 2:
m_dec = new ARM9Decoder(*new ARM9Interpreter(*this));
break;
}
} }
void ARM9Thread::DoPause() void ARM9Thread::DoPause()

View File

@ -2,6 +2,12 @@
#include "CPUInstrTable.h" #include "CPUInstrTable.h"
#pragma warning( disable : 4800 ) #pragma warning( disable : 4800 )
class CPUDecoder
{
public:
virtual void DecodeMemory(const u64 address)=0;
};
template<typename TO> template<typename TO>
class InstrCaller class InstrCaller
{ {

View File

@ -16,6 +16,8 @@ CPUThread::CPUThread(CPUThreadType type)
, m_sync_wait(false) , m_sync_wait(false)
, m_wait_thread_id(-1) , m_wait_thread_id(-1)
, m_free_data(false) , m_free_data(false)
, m_dec(nullptr)
, m_is_step(false)
{ {
} }
@ -94,11 +96,6 @@ bool CPUThread::Sync()
int CPUThread::ThreadStatus() int CPUThread::ThreadStatus()
{ {
if(m_is_step)
{
return CPUThread_Step;
}
if(Emu.IsStopped()) if(Emu.IsStopped())
{ {
return CPUThread_Stopped; return CPUThread_Stopped;
@ -109,6 +106,11 @@ int CPUThread::ThreadStatus()
return CPUThread_Break; return CPUThread_Break;
} }
if(m_is_step)
{
return CPUThread_Step;
}
if(Emu.IsPaused() || Sync()) if(Emu.IsPaused() || Sync())
{ {
return CPUThread_Sleeping; return CPUThread_Sleeping;
@ -223,6 +225,7 @@ void CPUThread::Stop()
Reset(); Reset();
DoStop(); DoStop();
Emu.CheckStatus(); Emu.CheckStatus();
delete m_dec;
wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this); wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this);
} }
@ -276,7 +279,7 @@ void CPUThread::Task()
continue; continue;
} }
DoCode(); m_dec->DecodeMemory(PC + m_offset);
NextPc(); NextPc();
if(status == CPUThread_Step) if(status == CPUThread_Step)

View File

@ -41,6 +41,8 @@ protected:
u32 m_exit_status; u32 m_exit_status;
CPUDecoder* m_dec;
public: public:
virtual void InitRegs()=0; virtual void InitRegs()=0;
@ -177,7 +179,6 @@ protected:
protected: protected:
virtual void Task(); virtual void Task();
virtual void DoCode() = 0;
}; };
CPUThread* GetCurrentCPUThread(); CPUThread* GetCurrentCPUThread();

View File

@ -0,0 +1,7 @@
#include "stdafx.h"
#include "PPCDecoder.h"
void PPCDecoder::DecodeMemory(const u64 address)
{
Decode(Memory.Read32(address));
}

View File

@ -2,15 +2,12 @@
#include "Emu/CPU/CPUDecoder.h" #include "Emu/CPU/CPUDecoder.h"
#include "PPCInstrTable.h" #include "PPCInstrTable.h"
class PPCDecoder class PPCDecoder : public CPUDecoder
{ {
protected:
u32 m_code;
public: public:
u32 GetCode() const { return m_code; }
virtual void Decode(const u32 code)=0; virtual void Decode(const u32 code)=0;
virtual void DecodeMemory(const u64 address);
}; };

View File

@ -14,9 +14,7 @@ PPCThread* GetCurrentPPCThread()
return (PPCThread*)thread; return (PPCThread*)thread;
} }
PPCThread::PPCThread(CPUThreadType type) PPCThread::PPCThread(CPUThreadType type) : CPUThread(type)
: CPUThread(type)
, m_dec(nullptr)
{ {
} }

View File

@ -6,7 +6,6 @@
class PPCThread : public CPUThread class PPCThread : public CPUThread
{ {
protected: protected:
PPCDecoder* m_dec;
u64 m_args[4]; u64 m_args[4];
Array<u64> m_argv_addr; Array<u64> m_argv_addr;

View File

@ -178,45 +178,6 @@ void PPUThread::DoStop()
bool dump_enable = false; bool dump_enable = false;
void PPUThread::DoCode()
{
const u32 code = Memory.Read32(m_offset + PC);
#ifdef _DEBUG
static bool is_last_enabled = false;
if(dump_enable)
{
static wxFile f("dump.txt", wxFile::write);
static PPU_DisAsm disasm(*this, DumpMode);
static PPU_Decoder decoder(disasm);
if(!is_last_enabled)
{
f.Write(RegsToString() + "\n");
}
disasm.dump_pc = PC;
decoder.Decode(code);
f.Write(disasm.last_opcode);
is_last_enabled = true;
}
else
{
is_last_enabled = false;
}
#endif
if(++cycle > 220)
{
cycle = 0;
TB++;
}
m_dec->Decode(code);
}
bool FPRdouble::IsINF(PPCdouble d) bool FPRdouble::IsINF(PPCdouble d)
{ {
return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL; return ((u64&)d & 0x7FFFFFFFFFFFFFFFULL) == 0x7FF0000000000000ULL;

View File

@ -827,8 +827,6 @@ protected:
virtual void DoPause(); virtual void DoPause();
virtual void DoResume(); virtual void DoResume();
virtual void DoStop(); virtual void DoStop();
virtual void DoCode();
}; };
PPUThread& GetCurrentPPUThread(); PPUThread& GetCurrentPPUThread();

View File

@ -311,7 +311,7 @@ void RawSPUThread::Task()
SPU.Status.SetValue(SPU_STATUS_RUNNING); SPU.Status.SetValue(SPU_STATUS_RUNNING);
} }
DoCode(); m_dec->DecodeMemory(PC + m_offset);
NextPc(); NextPc();
for(uint i=0; i<bp.GetCount(); ++i) for(uint i=0; i<bp.GetCount(); ++i)

View File

@ -87,8 +87,3 @@ void SPUThread::DoStop()
delete m_dec; delete m_dec;
m_dec = 0; m_dec = 0;
} }
void SPUThread::DoCode()
{
m_dec->Decode(Memory.Read32(m_offset + PC));
}

View File

@ -364,9 +364,6 @@ protected:
virtual void DoPause(); virtual void DoPause();
virtual void DoResume(); virtual void DoResume();
virtual void DoStop(); virtual void DoStop();
protected:
virtual void DoCode();
}; };
SPUThread& GetCurrentSPUThread(); SPUThread& GetCurrentSPUThread();

View File

@ -248,6 +248,86 @@ bool MemoryBlock::Write128(const u64 addr, const u128 value)
return true; return true;
} }
bool MemoryBlockLE::Read8(const u64 addr, u8* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u8*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read16(const u64 addr, u16* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u16*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read32(const u64 addr, u32* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u32*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read64(const u64 addr, u64* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u64*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Read128(const u64 addr, u128* value)
{
if(!IsMyAddress(addr)) return false;
*value = *(u128*)GetMem(FixAddr(addr));
return true;
}
bool MemoryBlockLE::Write8(const u64 addr, const u8 value)
{
if(!IsMyAddress(addr)) return false;
*(u8*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write16(const u64 addr, const u16 value)
{
if(!IsMyAddress(addr)) return false;
*(u16*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write32(const u64 addr, const u32 value)
{
if(!IsMyAddress(addr)) return false;
*(u32*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write64(const u64 addr, const u64 value)
{
if(!IsMyAddress(addr)) return false;
*(u64*)GetMem(FixAddr(addr)) = value;
return true;
}
bool MemoryBlockLE::Write128(const u64 addr, const u128 value)
{
if(!IsMyAddress(addr)) return false;
*(u128*)GetMem(FixAddr(addr)) = value;
return true;
}
//NullMemoryBlock //NullMemoryBlock
bool NullMemoryBlock::Read8(const u64 addr, u8* WXUNUSED(value)) bool NullMemoryBlock::Read8(const u64 addr, u8* WXUNUSED(value))
{ {
@ -320,11 +400,13 @@ bool NullMemoryBlock::Write128(const u64 addr, const u128 value)
} }
//DynamicMemoryBlock //DynamicMemoryBlock
DynamicMemoryBlock::DynamicMemoryBlock() : m_max_size(0) template<typename PT>
DynamicMemoryBlockBase<PT>::DynamicMemoryBlockBase() : m_max_size(0)
{ {
} }
const u32 DynamicMemoryBlock::GetUsedSize() const template<typename PT>
const u32 DynamicMemoryBlockBase<PT>::GetUsedSize() const
{ {
u32 size = 0; u32 size = 0;
@ -336,17 +418,20 @@ const u32 DynamicMemoryBlock::GetUsedSize() const
return size; return size;
} }
bool DynamicMemoryBlock::IsInMyRange(const u64 addr) template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr)
{ {
return addr >= GetStartAddr() && addr < GetStartAddr() + GetSize(); return addr >= GetStartAddr() && addr < GetStartAddr() + GetSize();
} }
bool DynamicMemoryBlock::IsInMyRange(const u64 addr, const u32 size) template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsInMyRange(const u64 addr, const u32 size)
{ {
return IsInMyRange(addr) && IsInMyRange(addr + size - 1); return IsInMyRange(addr) && IsInMyRange(addr + size - 1);
} }
bool DynamicMemoryBlock::IsMyAddress(const u64 addr) template<typename PT>
bool DynamicMemoryBlockBase<PT>::IsMyAddress(const u64 addr)
{ {
for(u32 i=0; i<m_used_mem.GetCount(); ++i) for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{ {
@ -359,7 +444,8 @@ bool DynamicMemoryBlock::IsMyAddress(const u64 addr)
return false; return false;
} }
MemoryBlock* DynamicMemoryBlock::SetRange(const u64 start, const u32 size) template<typename PT>
MemoryBlock* DynamicMemoryBlockBase<PT>::SetRange(const u64 start, const u32 size)
{ {
m_max_size = size; m_max_size = size;
MemoryBlock::SetRange(start, 0); MemoryBlock::SetRange(start, 0);
@ -367,7 +453,8 @@ MemoryBlock* DynamicMemoryBlock::SetRange(const u64 start, const u32 size)
return this; return this;
} }
void DynamicMemoryBlock::Delete() template<typename PT>
void DynamicMemoryBlockBase<PT>::Delete()
{ {
m_used_mem.Clear(); m_used_mem.Clear();
m_max_size = 0; m_max_size = 0;
@ -375,7 +462,8 @@ void DynamicMemoryBlock::Delete()
MemoryBlock::Delete(); MemoryBlock::Delete();
} }
bool DynamicMemoryBlock::Alloc(u64 addr, u32 size) template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc(u64 addr, u32 size)
{ {
if(!IsInMyRange(addr, size)) if(!IsInMyRange(addr, size))
{ {
@ -398,12 +486,14 @@ bool DynamicMemoryBlock::Alloc(u64 addr, u32 size)
return true; return true;
} }
void DynamicMemoryBlock::AppendUsedMem(u64 addr, u32 size) template<typename PT>
void DynamicMemoryBlockBase<PT>::AppendUsedMem(u64 addr, u32 size)
{ {
m_used_mem.Move(new MemBlockInfo(addr, size)); m_used_mem.Move(new MemBlockInfo(addr, size));
} }
u64 DynamicMemoryBlock::Alloc(u32 size) template<typename PT>
u64 DynamicMemoryBlockBase<PT>::Alloc(u32 size)
{ {
for(u64 addr=GetStartAddr(); addr <= GetEndAddr() - size;) for(u64 addr=GetStartAddr(); addr <= GetEndAddr() - size;)
{ {
@ -430,12 +520,14 @@ u64 DynamicMemoryBlock::Alloc(u32 size)
return 0; return 0;
} }
bool DynamicMemoryBlock::Alloc() template<typename PT>
bool DynamicMemoryBlockBase<PT>::Alloc()
{ {
return Alloc(GetSize() - GetUsedSize()) != 0; return Alloc(GetSize() - GetUsedSize()) != 0;
} }
bool DynamicMemoryBlock::Free(u64 addr) template<typename PT>
bool DynamicMemoryBlockBase<PT>::Free(u64 addr)
{ {
for(u32 i=0; i<m_used_mem.GetCount(); ++i) for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{ {
@ -449,7 +541,8 @@ bool DynamicMemoryBlock::Free(u64 addr)
return false; return false;
} }
u8* DynamicMemoryBlock::GetMem(u64 addr) const template<typename PT>
u8* DynamicMemoryBlockBase<PT>::GetMem(u64 addr) const
{ {
for(u32 i=0; i<m_used_mem.GetCount(); ++i) for(u32 i=0; i<m_used_mem.GetCount(); ++i)
{ {

View File

@ -4,7 +4,8 @@
enum MemoryType enum MemoryType
{ {
Memory_PS3, Memory_PS3,
Memory_Vita, Memory_PSV,
Memory_PSP,
}; };
class MemoryBase class MemoryBase
@ -13,6 +14,7 @@ class MemoryBase
public: public:
ArrayF<MemoryBlock> MemoryBlocks; ArrayF<MemoryBlock> MemoryBlocks;
MemoryBlock* UserMemory;
DynamicMemoryBlock MainMem; DynamicMemoryBlock MainMem;
DynamicMemoryBlock PRXMem; DynamicMemoryBlock PRXMem;
@ -23,6 +25,21 @@ public:
MemoryBlock SpuRawMem; MemoryBlock SpuRawMem;
MemoryBlock SpuThrMem; MemoryBlock SpuThrMem;
struct
{
DynamicMemoryBlockLE RAM;
DynamicMemoryBlockLE Userspace;
} PSVMemory;
struct
{
DynamicMemoryBlockLE Scratchpad;
DynamicMemoryBlockLE VRAM;
DynamicMemoryBlockLE RAM;
DynamicMemoryBlockLE Kernel;
DynamicMemoryBlockLE Userspace;
} PSPMemory;
bool m_inited; bool m_inited;
MemoryBase() MemoryBase()
@ -143,7 +160,7 @@ public:
{ {
case Memory_PS3: case Memory_PS3:
MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000)); MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000));
MemoryBlocks.Add(PRXMem.SetRange(0x30000000, 0x10000000)); MemoryBlocks.Add(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000));
MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000)); MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000));
MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000)); MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000));
MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000)); MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000));
@ -152,7 +169,17 @@ public:
//MemoryBlocks.Add(SpuThrMem.SetRange(0xF0000000, 0x10000000)); //MemoryBlocks.Add(SpuThrMem.SetRange(0xF0000000, 0x10000000));
break; break;
case Memory_Vita: case Memory_PSV:
MemoryBlocks.Add(PSVMemory.RAM.SetRange(0x81000000, 0x10000000));
MemoryBlocks.Add(UserMemory = PSVMemory.Userspace.SetRange(0x91000000, 0x10000000));
break;
case Memory_PSP:
MemoryBlocks.Add(PSPMemory.Scratchpad.SetRange(0x00010000, 0x00004000));
MemoryBlocks.Add(PSPMemory.VRAM.SetRange(0x04000000, 0x00200000));
MemoryBlocks.Add(PSPMemory.RAM.SetRange(0x08000000, 0x02000000));
MemoryBlocks.Add(PSPMemory.Kernel.SetRange(0x88000000, 0x00800000));
MemoryBlocks.Add(UserMemory = PSPMemory.Userspace.SetRange(0x08800000, 0x01800000));
break; break;
} }
@ -315,22 +342,22 @@ public:
u32 GetUserMemTotalSize() u32 GetUserMemTotalSize()
{ {
return PRXMem.GetSize(); return UserMemory->GetSize();
} }
u32 GetUserMemAvailSize() u32 GetUserMemAvailSize()
{ {
return PRXMem.GetSize() - PRXMem.GetUsedSize(); return UserMemory->GetSize() - UserMemory->GetUsedSize();
} }
u64 Alloc(const u32 size, const u32 align) u64 Alloc(const u32 size, const u32 align)
{ {
return PRXMem.Alloc(AlignAddr(size, align)); return UserMemory->Alloc(AlignAddr(size, align));
} }
bool Free(const u64 addr) bool Free(const u64 addr)
{ {
return PRXMem.Free(addr); return UserMemory->Free(addr);
} }
bool Map(const u64 dst_addr, const u64 src_addr, const u32 size) bool Map(const u64 dst_addr, const u64 src_addr, const u32 size)
@ -353,7 +380,7 @@ public:
{ {
if(MemoryBlocks[i].GetStartAddr() == addr) if(MemoryBlocks[i].GetStartAddr() == addr)
{ {
MemoryBlocks.RemoveFAt(i); MemoryBlocks.RemoveAt(i);
} }
} }
} }

View File

@ -98,8 +98,30 @@ public:
const u64 GetStartAddr() const { return range_start; } const u64 GetStartAddr() const { return range_start; }
const u64 GetEndAddr() const { return GetStartAddr() + GetSize() - 1; } const u64 GetEndAddr() const { return GetStartAddr() + GetSize() - 1; }
virtual const u32 GetSize() const { return range_size; } virtual const u32 GetSize() const { return range_size; }
virtual const u32 GetUsedSize() const { return GetSize(); }
u8* GetMem() const { return mem; } u8* GetMem() const { return mem; }
virtual u8* GetMem(u64 addr) const { return mem + addr; } virtual u8* GetMem(u64 addr) const { return mem + addr; }
virtual bool Alloc(u64 addr, u32 size) { return false; }
virtual u64 Alloc(u32 size) { return 0; }
virtual bool Alloc() { return false; }
virtual bool Free(u64 addr) { return false; }
};
class MemoryBlockLE : public MemoryBlock
{
public:
virtual bool Read8(const u64 addr, u8* value) override;
virtual bool Read16(const u64 addr, u16* value) override;
virtual bool Read32(const u64 addr, u32* value) override;
virtual bool Read64(const u64 addr, u64* value) override;
virtual bool Read128(const u64 addr, u128* value) override;
virtual bool Write8(const u64 addr, const u8 value) override;
virtual bool Write16(const u64 addr, const u16 value) override;
virtual bool Write32(const u64 addr, const u32 value) override;
virtual bool Write64(const u64 addr, const u64 value) override;
virtual bool Write128(const u64 addr, const u128 value) override;
}; };
class MemoryMirror : public MemoryBlock class MemoryMirror : public MemoryBlock
@ -145,32 +167,36 @@ class NullMemoryBlock : public MemoryBlock
virtual bool Write128(const u64 addr, const u128 value); virtual bool Write128(const u64 addr, const u128 value);
}; };
class DynamicMemoryBlock : public MemoryBlock template<typename PT>
class DynamicMemoryBlockBase : public PT
{ {
Array<MemBlockInfo> m_used_mem; Array<MemBlockInfo> m_used_mem;
u32 m_max_size; u32 m_max_size;
public: public:
DynamicMemoryBlock(); DynamicMemoryBlockBase();
const u32 GetSize() const { return m_max_size; } const u32 GetSize() const { return m_max_size; }
const u32 GetUsedSize() const; const u32 GetUsedSize() const;
bool IsInMyRange(const u64 addr); virtual bool IsInMyRange(const u64 addr);
bool IsInMyRange(const u64 addr, const u32 size); virtual bool IsInMyRange(const u64 addr, const u32 size);
bool IsMyAddress(const u64 addr); virtual bool IsMyAddress(const u64 addr);
MemoryBlock* SetRange(const u64 start, const u32 size); virtual MemoryBlock* SetRange(const u64 start, const u32 size);
virtual void Delete(); virtual void Delete();
bool Alloc(u64 addr, u32 size); virtual bool Alloc(u64 addr, u32 size);
u64 Alloc(u32 size); virtual u64 Alloc(u32 size);
bool Alloc(); virtual bool Alloc();
bool Free(u64 addr); virtual bool Free(u64 addr);
virtual u8* GetMem(u64 addr) const; virtual u8* GetMem(u64 addr) const;
private: private:
void AppendUsedMem(u64 addr, u32 size); void AppendUsedMem(u64 addr, u32 size);
}; };
typedef DynamicMemoryBlockBase<MemoryBlock> DynamicMemoryBlock;
typedef DynamicMemoryBlockBase<MemoryBlockLE> DynamicMemoryBlockLE;

View File

@ -123,6 +123,14 @@ void Emulator::Load()
case MACHINE_PPC64: case MACHINE_PPC64:
Memory.Init(Memory_PS3); Memory.Init(Memory_PS3);
break; break;
case MACHINE_MIPS:
Memory.Init(Memory_PSP);
break;
case MACHINE_ARM:
Memory.Init(Memory_PSV);
break;
} }
is_error = !l.Load(); is_error = !l.Load();
@ -148,6 +156,7 @@ void Emulator::Load()
{ {
case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break; case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break;
case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break; case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break;
case MACHINE_ARM: thread_type = CPU_THREAD_ARM9; break;
default: default:
is_error = true; is_error = true;

View File

@ -2,21 +2,21 @@ class InstructionEditorDialog
: public wxDialog : public wxDialog
{ {
u64 pc; u64 pc;
PPCDisAsm* disasm; CPUDisAsm* disasm;
PPCDecoder* decoder; CPUDecoder* decoder;
wxTextCtrl* t2_instr; wxTextCtrl* t2_instr;
wxStaticText* t3_preview; wxStaticText* t3_preview;
public: public:
PPCThread* CPU; CPUThread* CPU;
public: public:
InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm); InstructionEditorDialog(wxPanel *parent, u64 _pc, CPUThread* _CPU, CPUDecoder* _decoder, CPUDisAsm* _disasm);
void updatePreview(wxCommandEvent& event); void updatePreview(wxCommandEvent& event);
}; };
InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm) InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u64 _pc, CPUThread* _CPU, CPUDecoder* _decoder, CPUDisAsm* _disasm)
: wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition) : wxDialog(parent, wxID_ANY, "Edit instruction", wxDefaultPosition)
, pc(_pc) , pc(_pc)
, CPU(_CPU) , CPU(_CPU)
@ -90,11 +90,18 @@ void InstructionEditorDialog::updatePreview(wxCommandEvent& event)
unsigned long opcode; unsigned long opcode;
if (t2_instr->GetValue().ToULong(&opcode, 16)) if (t2_instr->GetValue().ToULong(&opcode, 16))
{ {
disasm->dump_pc = pc; if(CPU->GetType() == CPU_THREAD_ARM9)
decoder->Decode((u32)opcode); {
wxString preview = disasm->last_opcode; t3_preview->SetLabel("Preview for ARM9Thread not implemented yet.");
preview.Remove(0, preview.Find(':') + 1); }
t3_preview->SetLabel(preview); else
{
disasm->dump_pc = pc;
((PPCDecoder*)decoder)->Decode((u32)opcode);
wxString preview = disasm->last_opcode;
preview.Remove(0, preview.Find(':') + 1);
t3_preview->SetLabel(preview);
}
} }
else else
{ {

View File

@ -1,5 +1,11 @@
#include "stdafx.h" #include "stdafx.h"
#include "InterpreterDisAsm.h" #include "InterpreterDisAsm.h"
#include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUDisAsm.h"
#include "Emu/Cell/SPUDecoder.h"
#include "Emu/Cell/SPUDisAsm.h"
#include "Emu/ARM9/ARM9DisAsm.h"
#include "Emu/ARM9/ARM9Decoder.h"
#include "InstructionEditor.cpp" #include "InstructionEditor.cpp"
#include "RegisterEditor.cpp" #include "RegisterEditor.cpp"
@ -101,7 +107,7 @@ void InterpreterDisAsmFrame::UpdateUnitList()
void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event) void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{ {
CPU = (PPCThread*)event.GetClientData(); CPU = (CPUThread*)event.GetClientData();
delete decoder; delete decoder;
//delete disasm; //delete disasm;
@ -128,6 +134,14 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
disasm = &dis_asm; disasm = &dis_asm;
} }
break; break;
case CPU_THREAD_ARM9:
{
ARM9DisAsm& dis_asm = *new ARM9DisAsm(CPUDisAsm_InterpreterMode);
decoder = new ARM9Decoder(dis_asm);
disasm = &dis_asm;
}
break;
} }
} }
@ -228,7 +242,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr)
} }
disasm->dump_pc = PC; disasm->dump_pc = PC;
decoder->Decode(Memory.Read32(CPU->GetOffset() + PC)); decoder->DecodeMemory(CPU->GetOffset() + PC);
if(IsBreakPoint(PC)) if(IsBreakPoint(PC))
{ {
@ -303,7 +317,7 @@ void InterpreterDisAsmFrame::WriteRegs()
void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event) void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event)
{ {
PPCThread* thr = (PPCThread*)event.GetClientData(); CPUThread* thr = (CPUThread*)event.GetClientData();
event.Skip(); event.Skip();
if(!thr) if(!thr)

View File

@ -1,15 +1,13 @@
#pragma once #pragma once
#include "Emu/Cell/PPCThread.h" #include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/PPUDecoder.h" #include "Emu/CPU/CPUDecoder.h"
#include "Emu/Cell/PPUDisAsm.h" #include "Emu/CPU/CPUDisAsm.h"
#include "Emu/Cell/SPUDecoder.h"
#include "Emu/Cell/SPUDisAsm.h"
class InterpreterDisAsmFrame : public wxPanel class InterpreterDisAsmFrame : public wxPanel
{ {
wxListView* m_list; wxListView* m_list;
PPCDisAsm* disasm; CPUDisAsm* disasm;
PPCDecoder* decoder; CPUDecoder* decoder;
u64 PC; u64 PC;
Array<u32> remove_markedPC; Array<u32> remove_markedPC;
wxTextCtrl* m_regs; wxTextCtrl* m_regs;
@ -21,7 +19,7 @@ class InterpreterDisAsmFrame : public wxPanel
wxChoice* m_choice_units; wxChoice* m_choice_units;
public: public:
PPCThread* CPU; CPUThread* CPU;
public: public:
InterpreterDisAsmFrame(wxWindow* parent); InterpreterDisAsmFrame(wxWindow* parent);

View File

@ -1,23 +1,23 @@
class RegisterEditorDialog : public wxDialog class RegisterEditorDialog : public wxDialog
{ {
u64 pc; u64 pc;
PPCDisAsm* disasm; CPUDisAsm* disasm;
PPCDecoder* decoder; CPUDecoder* decoder;
wxComboBox* t1_register; wxComboBox* t1_register;
wxTextCtrl* t2_value; wxTextCtrl* t2_value;
wxStaticText* t3_preview; wxStaticText* t3_preview;
public: public:
PPCThread* CPU; CPUThread* CPU;
public: public:
RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm); RegisterEditorDialog(wxPanel *parent, u64 _pc, CPUThread* _CPU, CPUDecoder* _decoder, CPUDisAsm* _disasm);
void updateRegister(wxCommandEvent& event); void updateRegister(wxCommandEvent& event);
void updatePreview(wxCommandEvent& event); void updatePreview(wxCommandEvent& event);
}; };
RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread* _CPU, PPCDecoder* _decoder, PPCDisAsm* _disasm) RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, CPUThread* _CPU, CPUDecoder* _decoder, CPUDisAsm* _disasm)
: wxDialog(parent, wxID_ANY, "Edit registers", wxDefaultPosition) : wxDialog(parent, wxID_ANY, "Edit registers", wxDefaultPosition)
, pc(_pc) , pc(_pc)
, CPU(_CPU) , CPU(_CPU)
@ -82,6 +82,10 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u64 _pc, PPCThread*
case CPU_THREAD_RAW_SPU: case CPU_THREAD_RAW_SPU:
for (int i=0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]",i)); for (int i=0; i<128; i++) t1_register->Append(wxString::Format("GPR[%d]",i));
break; break;
default:
wxMessageBox("Not supported thread.", "Error");
return;
} }
SetSizerAndFit(s_panel_margin_x); SetSizerAndFit(s_panel_margin_x);

View File

@ -1,8 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "ELF32.h" #include "ELF32.h"
bool isLittleEndian;
ELF32Loader::ELF32Loader(vfsStream& f) ELF32Loader::ELF32Loader(vfsStream& f)
: elf32_f(f) : elf32_f(f)
, LoaderBase() , LoaderBase()
@ -38,29 +36,26 @@ bool ELF32Loader::Close()
bool ELF32Loader::LoadEhdrInfo() bool ELF32Loader::LoadEhdrInfo()
{ {
u8 endian;
elf32_f.Seek(5);
elf32_f.Read(&endian, 1);
isLittleEndian = (endian == 0x1);
elf32_f.Reset();
elf32_f.Seek(0); elf32_f.Seek(0);
if (isLittleEndian) ehdr.LoadLE(elf32_f); ehdr.Load(elf32_f);
else ehdr.Load(elf32_f);
if(!ehdr.CheckMagic()) return false; if(!ehdr.CheckMagic()) return false;
if(ehdr.IsLittleEndian())
ConLog.Warning("ELF32 LE");
switch(ehdr.e_machine) switch(ehdr.e_machine)
{ {
case MACHINE_MIPS: case MACHINE_MIPS:
case MACHINE_PPC64: case MACHINE_PPC64:
case MACHINE_SPU: case MACHINE_SPU:
case MACHINE_ARM:
machine = (Elf_Machine)ehdr.e_machine; machine = (Elf_Machine)ehdr.e_machine;
break; break;
default: default:
machine = MACHINE_Unknown; machine = MACHINE_Unknown;
ConLog.Error("Unknown elf32 type: 0x%x", ehdr.e_machine); ConLog.Error("Unknown elf32 machine: 0x%x", ehdr.e_machine);
return false; return false;
} }
@ -86,11 +81,25 @@ bool ELF32Loader::LoadPhdrInfo()
for(uint i=0; i<ehdr.e_phnum; ++i) for(uint i=0; i<ehdr.e_phnum; ++i)
{ {
Elf32_Phdr* phdr = new Elf32_Phdr(); Elf32_Phdr* phdr = new Elf32_Phdr();
if(isLittleEndian) phdr->LoadLE(elf32_f); if(ehdr.IsLittleEndian()) phdr->LoadLE(elf32_f);
else phdr->Load(elf32_f); else phdr->Load(elf32_f);
phdr_arr.Move(phdr); phdr_arr.Move(phdr);
} }
if(!Memory.IsGoodAddr(entry))
{
//entry is physical, convert to virtual
for(size_t i=0; i<phdr_arr.GetCount(); ++i)
{
if(phdr_arr[i].p_paddr >= entry && entry < phdr_arr[i].p_paddr + phdr_arr[i].p_memsz)
{
entry += phdr_arr[i].p_vaddr;
ConLog.Warning("virtual entry = 0x%x", entry);
break;
}
}
}
return true; return true;
} }
@ -100,7 +109,7 @@ bool ELF32Loader::LoadShdrInfo()
for(u32 i=0; i<ehdr.e_shnum; ++i) for(u32 i=0; i<ehdr.e_shnum; ++i)
{ {
Elf32_Shdr* shdr = new Elf32_Shdr(); Elf32_Shdr* shdr = new Elf32_Shdr();
if(isLittleEndian) shdr->LoadLE(elf32_f); if(ehdr.IsLittleEndian()) shdr->LoadLE(elf32_f);
else shdr->Load(elf32_f); else shdr->Load(elf32_f);
shdr_arr.Move(shdr); shdr_arr.Move(shdr);
} }
@ -138,8 +147,10 @@ bool ELF32Loader::LoadEhdrData(u64 offset)
return true; return true;
} }
bool ELF32Loader::LoadPhdrData(u64 offset) bool ELF32Loader::LoadPhdrData(u64 _offset)
{ {
const u64 offset = machine == MACHINE_SPU ? _offset : 0;
for(u32 i=0; i<phdr_arr.GetCount(); ++i) for(u32 i=0; i<phdr_arr.GetCount(); ++i)
{ {
phdr_arr[i].Show(); phdr_arr[i].Show();
@ -165,7 +176,16 @@ bool ELF32Loader::LoadPhdrData(u64 offset)
); );
} }
Memory.MainMem.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); switch(machine)
{
case MACHINE_SPU: Memory.MainMem.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
case MACHINE_MIPS: Memory.PSPMemory.RAM.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
case MACHINE_ARM: Memory.PSVMemory.RAM.Alloc(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
default:
continue;
}
elf32_f.Seek(phdr_arr[i].p_offset); elf32_f.Seek(phdr_arr[i].p_offset);
elf32_f.Read(&Memory[phdr_arr[i].p_vaddr + offset], phdr_arr[i].p_filesz); elf32_f.Read(&Memory[phdr_arr[i].p_vaddr + offset], phdr_arr[i].p_filesz);
} }
@ -173,7 +193,7 @@ bool ELF32Loader::LoadPhdrData(u64 offset)
{ {
elf32_f.Seek(phdr_arr[i].p_offset); elf32_f.Seek(phdr_arr[i].p_offset);
Elf32_Note note; Elf32_Note note;
if(isLittleEndian) note.LoadLE(elf32_f); if(ehdr.IsLittleEndian()) note.LoadLE(elf32_f);
else note.Load(elf32_f); else note.Load(elf32_f);
if(note.type != 1) if(note.type != 1)

View File

@ -48,6 +48,11 @@ struct Elf32_Ehdr
#endif #endif
} }
bool IsLittleEndian() const
{
return e_data == 1;
}
void Load(vfsStream& f) void Load(vfsStream& f)
{ {
e_magic = Read32(f); e_magic = Read32(f);
@ -55,43 +60,41 @@ struct Elf32_Ehdr
e_data = Read8(f); e_data = Read8(f);
e_curver = Read8(f); e_curver = Read8(f);
e_os_abi = Read8(f); e_os_abi = Read8(f);
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
void LoadLE(vfsStream& f) if(IsLittleEndian())
{ {
e_magic = Read32(f); e_abi_ver = Read64LE(f);
e_class = Read8(f); e_type = Read16LE(f);
e_data = Read8(f); e_machine = Read16LE(f);
e_curver = Read8(f); e_version = Read32LE(f);
e_os_abi = Read8(f); e_entry = Read32LE(f);
e_abi_ver = Read64LE(f); e_phoff = Read32LE(f);
e_type = Read16LE(f); e_shoff = Read32LE(f);
e_machine = Read16LE(f); e_flags = Read32LE(f);
e_version = Read32LE(f); e_ehsize = Read16LE(f);
e_entry = Read32LE(f); e_phentsize = Read16LE(f);
e_phoff = Read32LE(f); e_phnum = Read16LE(f);
e_shoff = Read32LE(f); e_shentsize = Read16LE(f);
e_flags = Read32LE(f); e_shnum = Read16LE(f);
e_ehsize = Read16LE(f); e_shstrndx = Read16LE(f);
e_phentsize = Read16LE(f); }
e_phnum = Read16LE(f); else
e_shentsize = Read16LE(f); {
e_shnum = Read16LE(f); e_abi_ver = Read64(f);
e_shstrndx = Read16LE(f); e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
} }
bool CheckMagic() const { return e_magic == 0x7F454C46; } bool CheckMagic() const { return e_magic == 0x7F454C46; }

View File

@ -42,8 +42,9 @@ const wxString Ehdr_MachineToString(const u16 machine)
switch(machine) switch(machine)
{ {
case MACHINE_MIPS: return "MIPS"; case MACHINE_MIPS: return "MIPS";
case MACHINE_PPC64: return "PowerPC64"; case MACHINE_PPC64: return "PowerPC64";
case MACHINE_SPU: return "SPU"; case MACHINE_SPU: return "SPU";
case MACHINE_ARM: return "ARM";
}; };
return wxString::Format("Unknown (%x)", machine); return wxString::Format("Unknown (%x)", machine);

View File

@ -11,6 +11,7 @@ enum Elf_Machine
MACHINE_MIPS = 0x08, MACHINE_MIPS = 0x08,
MACHINE_PPC64 = 0x15, MACHINE_PPC64 = 0x15,
MACHINE_SPU = 0x17, MACHINE_SPU = 0x17,
MACHINE_ARM = 0x28,
}; };
enum ShdrType enum ShdrType

View File

@ -203,6 +203,7 @@
<ClCompile Include="AppConnector.cpp" /> <ClCompile Include="AppConnector.cpp" />
<ClCompile Include="Emu\ARM9\ARM9Thread.cpp" /> <ClCompile Include="Emu\ARM9\ARM9Thread.cpp" />
<ClCompile Include="Emu\Cell\MFC.cpp" /> <ClCompile Include="Emu\Cell\MFC.cpp" />
<ClCompile Include="Emu\Cell\PPCDecoder.cpp" />
<ClCompile Include="Emu\Cell\PPCThread.cpp" /> <ClCompile Include="Emu\Cell\PPCThread.cpp" />
<ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" /> <ClCompile Include="Emu\Cell\PPUProgramCompiler.cpp" />
<ClCompile Include="Emu\Cell\PPUThread.cpp" /> <ClCompile Include="Emu\Cell\PPUThread.cpp" />

View File

@ -322,6 +322,9 @@
<ClCompile Include="Emu\ARM9\ARM9Thread.cpp"> <ClCompile Include="Emu\ARM9\ARM9Thread.cpp">
<Filter>Emu\ARM9</Filter> <Filter>Emu\ARM9</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Emu\Cell\PPCDecoder.cpp">
<Filter>Emu\Cell</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="rpcs3.rc" /> <ResourceCompile Include="rpcs3.rc" />