#pragma once
#include <vector>
class ThunkManager;
namespace MIPSComp {
class Jit;
class JitSafeMem {
public:
JitSafeMem(Jit *jit, MIPSGPReg raddr, s32 offset, u32 alignMask = 0xFFFFFFFF);
bool PrepareWrite(Gen::OpArg &dest, int size);
bool PrepareSlowWrite();
void DoSlowWrite(const void *safeFunc, const Gen::OpArg& src, int suboffset = 0);
template <typename T>
void DoSlowWrite(void (*safeFunc)(T val, u32 addr), const Gen::OpArg& src, int suboffset = 0) {
DoSlowWrite((const void *)safeFunc, src, suboffset);
}
bool PrepareRead(Gen::OpArg &src, int size);
bool PrepareSlowRead(const void *safeFunc);
template <typename T>
bool PrepareSlowRead(T (*safeFunc)(u32 addr)) {
return PrepareSlowRead((const void *)safeFunc);
}
void Finish();
Gen::OpArg NextFastAddress(int suboffset);
void NextSlowRead(const void *safeFunc, int suboffset);
template <typename T>
void NextSlowRead(T (*safeFunc)(u32 addr), int suboffset) {
NextSlowRead((const void *)safeFunc, suboffset);
}
private:
enum MemoryOpType {
MEM_READ,
MEM_WRITE,
};
Gen::OpArg PrepareMemoryOpArg(MemoryOpType type);
void PrepareSlowAccess();
bool ImmValid();
void IndirectCALL(const void *safeFunc);
Jit *jit_;
MIPSGPReg raddr_;
s32 offset_;
int size_;
bool needsCheck_;
bool needsSkip_;
bool fast_;
u32 alignMask_;
u32 iaddr_;
Gen::X64Reg xaddr_;
Gen::FixupBranch tooLow_, tooHigh_, skip_;
std::vector<Gen::FixupBranch> skipChecks_;
const u8 *safe_;
};
class JitSafeMemFuncs : public Gen::XCodeBlock
{
public:
JitSafeMemFuncs() {
}
~JitSafeMemFuncs() {
Shutdown();
}
void Init(ThunkManager *thunks);
void Shutdown();
const u8 *readU32;
const u8 *readU16;
const u8 *readU8;
const u8 *writeU32;
const u8 *writeU16;
const u8 *writeU8;
private:
void CreateReadFunc(int bits, const void *fallbackFunc);
void CreateWriteFunc(int bits, const void *fallbackFunc);
void CheckDirectEAX();
void StartDirectAccess();
std::vector<Gen::FixupBranch> skips_;
ThunkManager *thunks_;
};
};