2007-12-09 22:01:01 +00:00
|
|
|
#include "BasicBlock.h"
|
|
|
|
#include "MipsCodeGen.h"
|
|
|
|
#include "MemStream.h"
|
|
|
|
#include "offsetof_def.h"
|
2009-05-02 15:35:49 +00:00
|
|
|
#ifdef ARM
|
|
|
|
#include <mach/mach_init.h>
|
|
|
|
#include <mach/vm_map.h>
|
|
|
|
extern "C" void __clear_cache(void* begin, void* end);
|
|
|
|
#endif
|
2007-12-09 22:01:01 +00:00
|
|
|
|
|
|
|
using namespace Framework;
|
|
|
|
|
|
|
|
CBasicBlock::CBasicBlock(CMIPS& context, uint32 begin, uint32 end) :
|
|
|
|
m_begin(begin),
|
|
|
|
m_end(end),
|
|
|
|
m_context(context),
|
2008-03-19 11:30:45 +00:00
|
|
|
m_text(NULL),
|
2009-06-06 15:38:03 +00:00
|
|
|
m_textSize(0),
|
2008-06-30 18:58:04 +00:00
|
|
|
m_selfLoopCount(0),
|
|
|
|
m_branchHint(NULL)
|
2007-12-09 22:01:01 +00:00
|
|
|
{
|
|
|
|
assert(m_end >= m_begin);
|
|
|
|
}
|
|
|
|
|
|
|
|
CBasicBlock::~CBasicBlock()
|
|
|
|
{
|
|
|
|
if(m_text != NULL)
|
|
|
|
{
|
2009-05-09 16:17:21 +00:00
|
|
|
#ifdef ARM
|
|
|
|
vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(m_text), m_textSize);
|
|
|
|
#else
|
2007-12-09 22:01:01 +00:00
|
|
|
delete [] m_text;
|
2009-05-09 16:17:21 +00:00
|
|
|
#endif
|
|
|
|
|
2007-12-09 22:01:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBasicBlock::Compile()
|
|
|
|
{
|
|
|
|
CMemStream stream;
|
|
|
|
{
|
2008-01-09 06:07:59 +00:00
|
|
|
CMipsCodeGen codeGen;
|
|
|
|
|
|
|
|
for(unsigned int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
codeGen.SetVariableAsConstant(
|
|
|
|
offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]),
|
|
|
|
0
|
|
|
|
);
|
|
|
|
}
|
|
|
|
codeGen.SetStream(&stream);
|
2008-04-09 02:52:38 +00:00
|
|
|
codeGen.Begin();
|
2009-06-06 15:38:03 +00:00
|
|
|
CompileRange(codeGen);
|
2008-01-09 06:07:59 +00:00
|
|
|
codeGen.DumpVariables(0);
|
2009-05-02 15:35:49 +00:00
|
|
|
codeGen.EndQuota();
|
2008-01-09 06:07:59 +00:00
|
|
|
codeGen.End();
|
2007-12-09 22:01:01 +00:00
|
|
|
}
|
|
|
|
|
2009-05-02 15:35:49 +00:00
|
|
|
#ifdef ARM
|
|
|
|
vm_size_t page_size = 0;
|
|
|
|
host_page_size(mach_task_self(), &page_size);
|
|
|
|
unsigned int allocSize = ((stream.GetSize() + page_size - 1) / page_size) * page_size;
|
|
|
|
vm_allocate(mach_task_self(), reinterpret_cast<vm_address_t*>(&m_text), allocSize, TRUE);
|
|
|
|
memcpy(m_text, stream.GetBuffer(), stream.GetSize());
|
|
|
|
__clear_cache(m_text, m_text + stream.GetSize());
|
|
|
|
kern_return_t result = vm_protect(mach_task_self(), reinterpret_cast<vm_address_t>(m_text),
|
|
|
|
stream.GetSize(), 0, VM_PROT_READ | VM_PROT_EXECUTE);
|
|
|
|
assert(result == 0);
|
2009-05-09 16:17:21 +00:00
|
|
|
m_textSize = allocSize;
|
2009-05-02 15:35:49 +00:00
|
|
|
#else
|
2007-12-09 22:01:01 +00:00
|
|
|
//Save text
|
|
|
|
m_text = new uint8[stream.GetSize()];
|
2009-05-09 16:17:21 +00:00
|
|
|
m_textSize = stream.GetSize();
|
|
|
|
memcpy(m_text, stream.GetBuffer(), stream.GetSize());
|
2009-05-02 15:35:49 +00:00
|
|
|
#endif
|
2007-12-09 22:01:01 +00:00
|
|
|
}
|
|
|
|
|
2009-06-06 15:38:03 +00:00
|
|
|
void CBasicBlock::CompileRange(CCodeGen& codeGen)
|
|
|
|
{
|
|
|
|
for(uint32 address = m_begin; address <= m_end; address += 4)
|
|
|
|
{
|
|
|
|
m_context.m_pArch->CompileInstruction(
|
|
|
|
address,
|
|
|
|
&codeGen,
|
|
|
|
&m_context);
|
|
|
|
//Sanity check
|
|
|
|
//assert(codeGen.AreAllRegistersFreed());
|
|
|
|
assert(codeGen.IsStackEmpty());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:01:01 +00:00
|
|
|
unsigned int CBasicBlock::Execute()
|
|
|
|
{
|
2007-12-11 21:54:23 +00:00
|
|
|
volatile void* function = m_text;
|
|
|
|
volatile CMIPS* context = &m_context;
|
2007-12-09 22:01:01 +00:00
|
|
|
|
2008-02-25 13:11:29 +00:00
|
|
|
#ifdef AMD64
|
|
|
|
|
2009-05-02 15:35:49 +00:00
|
|
|
#elif defined(ARM)
|
|
|
|
|
2009-05-09 16:17:21 +00:00
|
|
|
__asm__ ("mov r1, %0" : : "r"(context) : "r1");
|
|
|
|
__asm__ ("mov r0, %0" : : "r"(function) : "r0");
|
|
|
|
__asm__ ("stmdb sp!, {r2, r3, r4, r5, r6, r7, r11, ip}");
|
|
|
|
__asm__ ("mov r11, r1");
|
2009-05-02 15:35:49 +00:00
|
|
|
__asm__ ("blx r0");
|
2009-05-09 16:17:21 +00:00
|
|
|
__asm__ ("ldmia sp!, {r2, r3, r4, r5, r6, r7, r11, ip}");
|
2009-05-02 15:35:49 +00:00
|
|
|
|
2008-02-25 13:11:29 +00:00
|
|
|
#else
|
|
|
|
|
2008-01-23 03:34:37 +00:00
|
|
|
//Should change pre-proc definitions used here (MACOSX to GCC?)
|
2007-12-09 22:01:01 +00:00
|
|
|
__asm
|
|
|
|
{
|
2008-01-23 03:34:37 +00:00
|
|
|
#if defined(MACOSX)
|
2008-05-04 19:59:53 +00:00
|
|
|
mov eax, esp
|
|
|
|
sub eax, 0x04
|
|
|
|
and eax, 0x0F
|
|
|
|
sub esp, eax //Keep stack aligned on 0x10 bytes
|
2008-01-21 20:33:31 +00:00
|
|
|
pusha
|
2008-01-23 03:34:37 +00:00
|
|
|
#elif defined(_MSVC)
|
|
|
|
pushad
|
2008-01-21 20:33:31 +00:00
|
|
|
#endif
|
|
|
|
|
2007-12-11 21:54:23 +00:00
|
|
|
mov eax, function
|
|
|
|
mov ebp, context
|
2007-12-09 22:01:01 +00:00
|
|
|
call eax
|
2007-12-12 03:09:57 +00:00
|
|
|
|
2008-01-23 03:34:37 +00:00
|
|
|
#if defined(MACOSX)
|
2008-01-21 20:33:31 +00:00
|
|
|
popa
|
2008-05-04 19:59:53 +00:00
|
|
|
add esp, eax
|
2008-01-23 03:34:37 +00:00
|
|
|
#elif defined(_MSVC)
|
|
|
|
popad
|
2008-01-21 20:33:31 +00:00
|
|
|
#endif
|
2007-12-09 22:01:01 +00:00
|
|
|
}
|
2008-02-25 13:11:29 +00:00
|
|
|
#endif
|
2007-12-11 21:54:23 +00:00
|
|
|
|
2008-01-17 04:59:27 +00:00
|
|
|
if((m_context.m_State.nGPR[CMIPS::RA].nV0 & 3) != 0)
|
|
|
|
{
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
|
2007-12-09 22:01:01 +00:00
|
|
|
if(m_context.m_State.nDelayedJumpAddr != MIPS_INVALID_PC)
|
|
|
|
{
|
|
|
|
m_context.m_State.nPC = m_context.m_State.nDelayedJumpAddr;
|
|
|
|
m_context.m_State.nDelayedJumpAddr = MIPS_INVALID_PC;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_context.m_State.nPC = m_end + 4;
|
|
|
|
}
|
|
|
|
|
2008-05-02 00:55:54 +00:00
|
|
|
// if(m_context.m_State.pipeQ.target != MIPS_INVALID_PC)
|
|
|
|
// {
|
|
|
|
// uint32& target = m_context.m_State.pipeQ.target;
|
|
|
|
// if(m_end >= target)
|
|
|
|
// {
|
|
|
|
// m_context.m_State.nCOP2Q = m_context.m_State.pipeQ.heldValue;
|
|
|
|
// target = MIPS_INVALID_PC;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// uint32 remain = target - m_end;
|
|
|
|
// target = m_context.m_State.nPC + remain - 4;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
2007-12-09 22:01:01 +00:00
|
|
|
return ((m_end - m_begin) / 4) + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CBasicBlock::GetBeginAddress() const
|
|
|
|
{
|
|
|
|
return m_begin;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 CBasicBlock::GetEndAddress() const
|
|
|
|
{
|
|
|
|
return m_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBasicBlock::IsCompiled() const
|
|
|
|
{
|
|
|
|
return m_text != NULL;
|
|
|
|
}
|
2008-03-19 11:30:45 +00:00
|
|
|
|
|
|
|
unsigned int CBasicBlock::GetSelfLoopCount() const
|
|
|
|
{
|
|
|
|
return m_selfLoopCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBasicBlock::SetSelfLoopCount(unsigned int selfLoopCount)
|
|
|
|
{
|
|
|
|
m_selfLoopCount = selfLoopCount;
|
|
|
|
}
|
2008-06-30 18:58:04 +00:00
|
|
|
|
|
|
|
CBasicBlock* CBasicBlock::GetBranchHint() const
|
|
|
|
{
|
|
|
|
return m_branchHint;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBasicBlock::SetBranchHint(CBasicBlock* branchHint)
|
|
|
|
{
|
|
|
|
m_branchHint = branchHint;
|
|
|
|
}
|