From 2d6a730cac8c89b4b3e5d630a2c8d90c1108cda4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 8 Mar 2013 22:50:08 -0800 Subject: [PATCH] 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.) --- Core/MIPS/x86/CompFPU.cpp | 4 ++-- Core/MIPS/x86/CompLoadStore.cpp | 4 ++-- Core/MIPS/x86/CompVFPU.cpp | 8 ++++---- Core/MIPS/x86/Jit.cpp | 34 +++++++++++++++++++++++++++------ Core/MIPS/x86/Jit.h | 15 ++++++++++++--- 5 files changed, 48 insertions(+), 17 deletions(-) diff --git a/Core/MIPS/x86/CompFPU.cpp b/Core/MIPS/x86/CompFPU.cpp index 620fdc216a..e154df5170 100644 --- a/Core/MIPS/x86/CompFPU.cpp +++ b/Core/MIPS/x86/CompFPU.cpp @@ -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()) { diff --git a/Core/MIPS/x86/CompLoadStore.cpp b/Core/MIPS/x86/CompLoadStore.cpp index f0dc88e1d2..2ab903c4d0 100644 --- a/Core/MIPS/x86/CompLoadStore.cpp +++ b/Core/MIPS/x86/CompLoadStore.cpp @@ -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) { diff --git a/Core/MIPS/x86/CompVFPU.cpp b/Core/MIPS/x86/CompVFPU.cpp index c099e488e2..a2b0f34779 100644 --- a/Core/MIPS/x86/CompVFPU.cpp +++ b/Core/MIPS/x86/CompVFPU.cpp @@ -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])); diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index f2a7e0666d..a58aac5aff 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -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 diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 8cbfda4f82..2967655277 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -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_;