Add some basics for memory checks to x86 jit.

Specifically, we will need to be able to bail in delayslots,
and we will need to know the size of the access (useful anyway.)
This commit is contained in:
Unknown W. Brackets 2013-03-08 22:50:08 -08:00
parent 03e8ee3d52
commit 2d6a730cac
5 changed files with 48 additions and 17 deletions

View File

@ -106,7 +106,7 @@ void Jit::Comp_FPULS(u32 op)
JitSafeMem safe(this, rs, offset);
OpArg src;
if (safe.PrepareRead(src))
if (safe.PrepareRead(src, 4))
MOVSS(fpr.RX(ft), src);
if (safe.PrepareSlowRead((void *) &Memory::Read_U32))
{
@ -127,7 +127,7 @@ void Jit::Comp_FPULS(u32 op)
JitSafeMem safe(this, rs, offset);
OpArg dest;
if (safe.PrepareWrite(dest))
if (safe.PrepareWrite(dest, 4))
MOVSS(dest, fpr.RX(ft));
if (safe.PrepareSlowWrite())
{

View File

@ -53,7 +53,7 @@ namespace MIPSComp
JitSafeMem safe(this, rs, offset);
OpArg src;
if (safe.PrepareRead(src))
if (safe.PrepareRead(src, 4))
(this->*mov)(32, bits, gpr.RX(rt), src);
if (safe.PrepareSlowRead(safeFunc))
(this->*mov)(32, bits, gpr.RX(rt), R(EAX));
@ -83,7 +83,7 @@ namespace MIPSComp
JitSafeMem safe(this, rs, offset);
OpArg dest;
if (safe.PrepareWrite(dest))
if (safe.PrepareWrite(dest, 4))
{
if (needSwap)
{

View File

@ -210,7 +210,7 @@ void Jit::Comp_SV(u32 op) {
JitSafeMem safe(this, rs, imm);
safe.SetFar();
OpArg src;
if (safe.PrepareRead(src))
if (safe.PrepareRead(src, 4))
{
MOVSS(fpr.VX(vt), safe.NextFastAddress(0));
}
@ -236,7 +236,7 @@ void Jit::Comp_SV(u32 op) {
JitSafeMem safe(this, rs, imm);
safe.SetFar();
OpArg dest;
if (safe.PrepareWrite(dest))
if (safe.PrepareWrite(dest, 4))
{
MOVSS(safe.NextFastAddress(0), fpr.VX(vt));
}
@ -278,7 +278,7 @@ void Jit::Comp_SVQ(u32 op)
JitSafeMem safe(this, rs, imm);
safe.SetFar();
OpArg src;
if (safe.PrepareRead(src))
if (safe.PrepareRead(src, 16))
{
// Just copy 4 words the easiest way while not wasting registers.
for (int i = 0; i < 4; i++)
@ -312,7 +312,7 @@ void Jit::Comp_SVQ(u32 op)
JitSafeMem safe(this, rs, imm);
safe.SetFar();
OpArg dest;
if (safe.PrepareWrite(dest))
if (safe.PrepareWrite(dest, 16))
{
for (int i = 0; i < 4; i++)
MOVSS(safe.NextFastAddress(i * 4), fpr.VX(vregs[i]));

View File

@ -248,6 +248,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
js.curBlock = b;
js.compiling = true;
js.inDelaySlot = false;
js.needCheckCoreState = false;
js.PrefixStart();
// We add a check before the block, used when entering from a linked block.
@ -331,7 +332,10 @@ void Jit::WriteExit(u32 destination, int exit_num)
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
if (block >= 0 && jo.enableBlocklink) {
if (js.needCheckCoreState) {
MOV(32, M(&mips_->pc), Imm32(destination));
JMP(asm_.dispatcherCheckCoreState, true);
} else if (block >= 0 && jo.enableBlocklink) {
// It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true);
b->linkStatus[exit_num] = true;
@ -378,6 +382,8 @@ void Jit::WriteExitDestInEAX()
SUB(32, M(&currentMIPS->downcount), Imm32(0));
J_CC(CC_NE, asm_.dispatcher, true);
}
else if (js.needCheckCoreState)
JMP(asm_.dispatcherCheckCoreState, true);
else
JMP(asm_.dispatcher, true);
}
@ -422,13 +428,15 @@ void Jit::JitSafeMem::SetFar()
far_ = true;
}
bool Jit::JitSafeMem::PrepareWrite(OpArg &dest)
bool Jit::JitSafeMem::PrepareWrite(OpArg &dest, int size)
{
// If it's an immediate, we can do the write if valid.
if (iaddr_ != (u32) -1)
{
if (Memory::IsValidAddress(iaddr_))
{
MemCheckImm(MEM_WRITE, size);
#ifdef _M_IX86
dest = M(Memory::base + (iaddr_ & Memory::MEMVIEW32_MASK));
#else
@ -441,16 +449,18 @@ bool Jit::JitSafeMem::PrepareWrite(OpArg &dest)
}
// Otherwise, we always can do the write (conditionally.)
else
dest = PrepareMemoryOpArg();
dest = PrepareMemoryOpArg(MEM_WRITE, size);
return true;
}
bool Jit::JitSafeMem::PrepareRead(OpArg &src)
bool Jit::JitSafeMem::PrepareRead(OpArg &src, int size)
{
if (iaddr_ != (u32) -1)
{
if (Memory::IsValidAddress(iaddr_))
{
MemCheckImm(MEM_READ, size);
#ifdef _M_IX86
src = M(Memory::base + (iaddr_ & Memory::MEMVIEW32_MASK));
#else
@ -462,7 +472,7 @@ bool Jit::JitSafeMem::PrepareRead(OpArg &src)
return false;
}
else
src = PrepareMemoryOpArg();
src = PrepareMemoryOpArg(MEM_READ, size);
return true;
}
@ -486,7 +496,7 @@ OpArg Jit::JitSafeMem::NextFastAddress(int suboffset)
#endif
}
OpArg Jit::JitSafeMem::PrepareMemoryOpArg()
OpArg Jit::JitSafeMem::PrepareMemoryOpArg(ReadType type, int size)
{
// We may not even need to move into EAX as a temporary.
// TODO: Except on x86 in fastmem mode.
@ -501,6 +511,8 @@ OpArg Jit::JitSafeMem::PrepareMemoryOpArg()
xaddr_ = EAX;
}
MemCheckAsm(type, size);
if (!g_Config.bFastMemory)
{
// Is it in physical ram?
@ -636,6 +648,16 @@ void Jit::JitSafeMem::Finish()
jit_->SetJumpTarget(skip_);
}
void Jit::JitSafeMem::MemCheckImm(ReadType type, int size)
{
// TODO
}
void Jit::JitSafeMem::MemCheckAsm(ReadType type, int size)
{
// TODO
}
void Jit::Comp_DoNothing(u32 op) { }
} // namespace

View File

@ -60,6 +60,7 @@ struct JitState
u32 blockStart;
bool cancel;
bool inDelaySlot;
bool needCheckCoreState;
int downcountAmount;
int numInstructions;
bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block
@ -269,14 +270,14 @@ private:
JitSafeMem(Jit *jit, int raddr, s32 offset);
// Emit code necessary for a memory write, returns true if MOV to dest is needed.
bool PrepareWrite(OpArg &dest);
bool PrepareWrite(OpArg &dest, int size);
// Emit code proceeding a slow write call, returns true if slow write is needed.
bool PrepareSlowWrite();
// Emit a slow write from src.
void DoSlowWrite(void *safeFunc, const OpArg src, int suboffset = 0);
// Emit code necessary for a memory read, returns true if MOV from src is needed.
bool PrepareRead(OpArg &src);
bool PrepareRead(OpArg &src, int size);
// Emit code for a slow read call, and returns true if result is in EAX.
bool PrepareSlowRead(void *safeFunc);
@ -291,8 +292,16 @@ private:
void NextSlowRead(void *safeFunc, int suboffset);
private:
OpArg PrepareMemoryOpArg();
enum ReadType
{
MEM_READ,
MEM_WRITE,
};
OpArg PrepareMemoryOpArg(ReadType type, int size);
void PrepareSlowAccess();
void MemCheckImm(ReadType type, int size);
void MemCheckAsm(ReadType type, int size);
Jit *jit_;
int raddr_;