mirror of
https://github.com/libretro/ppsspp.git
synced 2025-04-03 04:01:33 +00:00
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:
parent
03e8ee3d52
commit
2d6a730cac
@ -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())
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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]));
|
||||
|
@ -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(¤tMIPS->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
|
||||
|
@ -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_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user