mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-25 01:00:01 +00:00
Assorted cleanup in the MIPS emulation
This commit is contained in:
parent
108edd4093
commit
2d8429ac48
@ -216,7 +216,6 @@ u8* MemArena::Find4GBBase()
|
|||||||
#else // 32 bit
|
#else // 32 bit
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// The highest thing in any 1GB section of memory space is the locked cache. We only need to fit it.
|
|
||||||
u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE);
|
u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE);
|
||||||
if (base) {
|
if (base) {
|
||||||
VirtualFree(base, 0, MEM_RELEASE);
|
VirtualFree(base, 0, MEM_RELEASE);
|
||||||
@ -244,8 +243,6 @@ u8* MemArena::Find4GBBase()
|
|||||||
// if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM))
|
// if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM))
|
||||||
// continue;
|
// continue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) {
|
static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) {
|
||||||
// OK, we know where to find free space. Now grab it!
|
// OK, we know where to find free space. Now grab it!
|
||||||
// We just mimic the popular BAT setup.
|
// We just mimic the popular BAT setup.
|
||||||
@ -384,6 +381,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||||||
u8 *base = MemArena::Find4GBBase();
|
u8 *base = MemArena::Find4GBBase();
|
||||||
if (!Memory_TryBase(base, views, num_views, flags, arena))
|
if (!Memory_TryBase(base, views, num_views, flags, arena))
|
||||||
{
|
{
|
||||||
|
ERROR_LOG(MEMMAP, "MemoryMap_Setup: Failed finding a memory base.");
|
||||||
PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
|
PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
// Currently known non working ones should have DISABLE.
|
// Currently known non working ones should have DISABLE.
|
||||||
|
|
||||||
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
|
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
|
||||||
|
|
||||||
#define CONDITIONAL_DISABLE ;
|
#define CONDITIONAL_DISABLE ;
|
||||||
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
|
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
|
||||||
#define NEON_IF_AVAILABLE(func) { if (jo.useNEONVFPU) { func(op); return; } }
|
#define NEON_IF_AVAILABLE(func) { if (jo.useNEONVFPU) { func(op); return; } }
|
||||||
@ -51,8 +52,6 @@
|
|||||||
#define _IMM16 (signed short)(op & 0xFFFF)
|
#define _IMM16 (signed short)(op & 0xFFFF)
|
||||||
#define _IMM26 (op & 0x03FFFFFF)
|
#define _IMM26 (op & 0x03FFFFFF)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace MIPSComp
|
namespace MIPSComp
|
||||||
{
|
{
|
||||||
// Vector regs can overlap in all sorts of swizzled ways.
|
// Vector regs can overlap in all sorts of swizzled ways.
|
||||||
@ -604,6 +603,7 @@ namespace MIPSComp
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Jit::Comp_VDot(MIPSOpcode op) {
|
void Jit::Comp_VDot(MIPSOpcode op) {
|
||||||
|
NEON_IF_AVAILABLE(CompNEON_VDot);
|
||||||
CONDITIONAL_DISABLE;
|
CONDITIONAL_DISABLE;
|
||||||
if (js.HasUnknownPrefix()) {
|
if (js.HasUnknownPrefix()) {
|
||||||
DISABLE;
|
DISABLE;
|
||||||
@ -1689,6 +1689,8 @@ namespace MIPSComp
|
|||||||
SetCC(CC_AL);
|
SetCC(CC_AL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyPrefixD(dregs, sz);
|
||||||
fpr.ReleaseSpillLocksAndDiscardTemps();
|
fpr.ReleaseSpillLocksAndDiscardTemps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,12 +149,6 @@ void Jit::ClearCacheAt(u32 em_address, int length)
|
|||||||
blocks.InvalidateICache(em_address, length);
|
blocks.InvalidateICache(em_address, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit::CompileAt(u32 addr)
|
|
||||||
{
|
|
||||||
MIPSOpcode op = Memory::Read_Instruction(addr);
|
|
||||||
MIPSCompileOp(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Jit::EatInstruction(MIPSOpcode op) {
|
void Jit::EatInstruction(MIPSOpcode op) {
|
||||||
MIPSInfo info = MIPSGetInfo(op);
|
MIPSInfo info = MIPSGetInfo(op);
|
||||||
if (info & DELAYSLOT) {
|
if (info & DELAYSLOT) {
|
||||||
@ -188,6 +182,7 @@ void Jit::CompileDelaySlot(int flags)
|
|||||||
_MSR(true, false, R8); // Restore flags register
|
_MSR(true, false, R8); // Restore flags register
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Jit::Compile(u32 em_address) {
|
void Jit::Compile(u32 em_address) {
|
||||||
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
|
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
|
||||||
ClearCache();
|
ClearCache();
|
||||||
|
@ -52,6 +52,7 @@ class Jit : public ArmGen::ARMXCodeBlock
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Jit(MIPSState *mips);
|
Jit(MIPSState *mips);
|
||||||
|
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
static void DoDummyState(PointerWrap &p);
|
static void DoDummyState(PointerWrap &p);
|
||||||
|
|
||||||
@ -70,7 +71,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CompileDelaySlot(int flags);
|
void CompileDelaySlot(int flags);
|
||||||
void CompileAt(u32 addr);
|
|
||||||
void EatInstruction(MIPSOpcode op);
|
void EatInstruction(MIPSOpcode op);
|
||||||
void Comp_RunBlock(MIPSOpcode op);
|
void Comp_RunBlock(MIPSOpcode op);
|
||||||
|
|
||||||
|
@ -217,14 +217,16 @@ int binary_search(JitBlock blocks[], const u8 *baseoff, int imin, int imax)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int JitBlockCache::GetBlockNumberFromEmuHackOp(MIPSOpcode inst) const {
|
int JitBlockCache::GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad) const {
|
||||||
if (!num_blocks || !MIPS_IS_EMUHACK(inst)) // definitely not a JIT block
|
if (!num_blocks || !MIPS_IS_EMUHACK(inst)) // definitely not a JIT block
|
||||||
return -1;
|
return -1;
|
||||||
int off = (inst & MIPS_EMUHACK_VALUE_MASK);
|
int off = (inst & MIPS_EMUHACK_VALUE_MASK);
|
||||||
|
|
||||||
const u8 *baseoff = codeBlock_->GetBasePtr() + off;
|
const u8 *baseoff = codeBlock_->GetBasePtr() + off;
|
||||||
if (baseoff < codeBlock_->GetBasePtr() || baseoff >= codeBlock_->GetCodePtr()) {
|
if (baseoff < codeBlock_->GetBasePtr() || baseoff >= codeBlock_->GetCodePtr()) {
|
||||||
ERROR_LOG(JIT, "JitBlockCache: Invalid Emuhack Op %08x", inst.encoding);
|
if (!ignoreBad) {
|
||||||
|
ERROR_LOG(JIT, "JitBlockCache: Invalid Emuhack Op %08x", inst.encoding);
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ public:
|
|||||||
// Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap.
|
// Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap.
|
||||||
// This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime.
|
// This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime.
|
||||||
void GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers);
|
void GetBlockNumbersFromAddress(u32 em_address, std::vector<int> *block_numbers);
|
||||||
int GetBlockNumberFromEmuHackOp(MIPSOpcode inst) const;
|
int GetBlockNumberFromEmuHackOp(MIPSOpcode inst, bool ignoreBad = false) const;
|
||||||
|
|
||||||
u32 GetAddressFromBlockPtr(const u8 *ptr) const;
|
u32 GetAddressFromBlockPtr(const u8 *ptr) const;
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ namespace MIPSComp {
|
|||||||
prefixTFlag = PREFIX_KNOWN_DIRTY;
|
prefixTFlag = PREFIX_KNOWN_DIRTY;
|
||||||
prefixT = 0xE4;
|
prefixT = 0xE4;
|
||||||
}
|
}
|
||||||
if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0 || VfpuWriteMask() != 0) {
|
if ((prefixDFlag & PREFIX_KNOWN) == 0 || prefixD != 0x0) {
|
||||||
prefixDFlag = PREFIX_KNOWN_DIRTY;
|
prefixDFlag = PREFIX_KNOWN_DIRTY;
|
||||||
prefixD = 0x0;
|
prefixD = 0x0;
|
||||||
}
|
}
|
||||||
|
@ -136,4 +136,8 @@ namespace MIPSCodeUtils
|
|||||||
bool IsVFPUBranch(MIPSOpcode op) {
|
bool IsVFPUBranch(MIPSOpcode op) {
|
||||||
return (MIPSGetInfo(op) & (IS_VFPU | IS_CONDBRANCH)) == (IS_VFPU | IS_CONDBRANCH);
|
return (MIPSGetInfo(op) & (IS_VFPU | IS_CONDBRANCH)) == (IS_VFPU | IS_CONDBRANCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsBranch(MIPSOpcode op) {
|
||||||
|
return (MIPSGetInfo(op) & IS_CONDBRANCH) == IS_CONDBRANCH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,4 +58,5 @@ namespace MIPSCodeUtils
|
|||||||
u32 GetJumpTarget(u32 addr);
|
u32 GetJumpTarget(u32 addr);
|
||||||
u32 GetSureBranchTarget(u32 addr);
|
u32 GetSureBranchTarget(u32 addr);
|
||||||
bool IsVFPUBranch(MIPSOpcode op);
|
bool IsVFPUBranch(MIPSOpcode op);
|
||||||
|
bool IsBranch(MIPSOpcode op);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,14 @@ namespace MIPSDis
|
|||||||
sprintf(out, "%s\t --- unknown ---", MIPSGetName(op));
|
sprintf(out, "%s\t --- unknown ---", MIPSGetName(op));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dis_Cache(MIPSOpcode op, char *out)
|
||||||
|
{
|
||||||
|
int imm = (s16)(op & 0xFFFF);
|
||||||
|
int rs = _RS;
|
||||||
|
int func = (op >> 16) & 0x1F;
|
||||||
|
sprintf(out, "%s\tfunc=%i, %s(%s)", MIPSGetName(op), func, RN(rs), SignedHex(imm));
|
||||||
|
}
|
||||||
|
|
||||||
void Dis_mxc1(MIPSOpcode op, char *out)
|
void Dis_mxc1(MIPSOpcode op, char *out)
|
||||||
{
|
{
|
||||||
int fs = _FS;
|
int fs = _FS;
|
||||||
|
@ -34,6 +34,7 @@ namespace MIPSDis
|
|||||||
void Dis_RelBranch2(MIPSOpcode op, char *out);
|
void Dis_RelBranch2(MIPSOpcode op, char *out);
|
||||||
void Dis_RelBranch(MIPSOpcode op, char *out);
|
void Dis_RelBranch(MIPSOpcode op, char *out);
|
||||||
void Dis_Generic(MIPSOpcode op, char *out);
|
void Dis_Generic(MIPSOpcode op, char *out);
|
||||||
|
void Dis_Cache(MIPSOpcode op, char *out);
|
||||||
void Dis_IType(MIPSOpcode op, char *out);
|
void Dis_IType(MIPSOpcode op, char *out);
|
||||||
void Dis_IType1(MIPSOpcode op, char *out);
|
void Dis_IType1(MIPSOpcode op, char *out);
|
||||||
void Dis_ITypeMem(MIPSOpcode op, char *out);
|
void Dis_ITypeMem(MIPSOpcode op, char *out);
|
||||||
|
@ -147,7 +147,7 @@ const MIPSInstruction tableImmediate[64] = // xxxxxx ..... ..... ...............
|
|||||||
INVALID,
|
INVALID,
|
||||||
INVALID,
|
INVALID,
|
||||||
INSTR("swr", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM|MEMTYPE_WORD),
|
INSTR("swr", &Jit::Comp_ITypeMem, Dis_ITypeMem, Int_ITypeMem, IN_IMM16|IN_RS_ADDR|IN_RT|OUT_MEM|MEMTYPE_WORD),
|
||||||
INSTR("cache", &Jit::Comp_Cache, Dis_Generic, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_OTHER),
|
INSTR("cache", &Jit::Comp_Cache, Dis_Cache, Int_Cache, IN_MEM|IN_IMM16|IN_RS_ADDR|IN_OTHER|OUT_OTHER),
|
||||||
//48
|
//48
|
||||||
INSTR("ll", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD),
|
INSTR("ll", &Jit::Comp_Generic, Dis_Generic, Int_StoreSync, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_RT|OUT_OTHER|MEMTYPE_WORD),
|
||||||
INSTR("lwc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|MEMTYPE_FLOAT),
|
INSTR("lwc1", &Jit::Comp_FPULS, Dis_FPULS, Int_FPULS, IN_MEM|IN_IMM16|IN_RS_ADDR|OUT_OTHER|MEMTYPE_FLOAT),
|
||||||
|
@ -86,6 +86,7 @@ struct MIPSInfo {
|
|||||||
|
|
||||||
#define VFPU_NO_PREFIX 0x10000000
|
#define VFPU_NO_PREFIX 0x10000000
|
||||||
#define IS_VFPU 0x20000000
|
#define IS_VFPU 0x20000000
|
||||||
|
#define IS_FPU 0x40000000
|
||||||
|
|
||||||
#ifndef CDECL
|
#ifndef CDECL
|
||||||
#define CDECL
|
#define CDECL
|
||||||
|
@ -259,7 +259,7 @@ MatrixSize GetMtxSize(MIPSOpcode op)
|
|||||||
a += (b<<1);
|
a += (b<<1);
|
||||||
switch (a)
|
switch (a)
|
||||||
{
|
{
|
||||||
case 0: ERROR_LOG_REPORT(CPU, "Unexpected matrix size 1x1."); return M_2x2;
|
case 0: return M_4x4; // This error pretty much only happens in disassembly of junk: // ERROR_LOG_REPORT(CPU, "Unexpected matrix size 1x1."); return M_2x2;
|
||||||
case 1: return M_2x2;
|
case 1: return M_2x2;
|
||||||
case 2: return M_3x3;
|
case 2: return M_3x3;
|
||||||
case 3: return M_4x4;
|
case 3: return M_4x4;
|
||||||
|
@ -492,7 +492,6 @@ void Jit::BranchVFPUFlag(MIPSOpcode op, Gen::CCFlags cc, bool likely)
|
|||||||
// THE CONDITION
|
// THE CONDITION
|
||||||
int imm3 = (op >> 18) & 7;
|
int imm3 = (op >> 18) & 7;
|
||||||
|
|
||||||
//int val = (mips_->vfpuCtrl[VFPU_CTRL_CC] >> imm3) & 1;
|
|
||||||
TEST(32, M((void *)&(mips_->vfpuCtrl[VFPU_CTRL_CC])), Imm32(1 << imm3));
|
TEST(32, M((void *)&(mips_->vfpuCtrl[VFPU_CTRL_CC])), Imm32(1 << imm3));
|
||||||
|
|
||||||
u32 notTakenTarget = js.compilerPC + (delaySlotIsBranch ? 4 : 8);
|
u32 notTakenTarget = js.compilerPC + (delaySlotIsBranch ? 4 : 8);
|
||||||
|
@ -722,6 +722,9 @@ void Jit::Comp_Vcmov(MIPSOpcode op) {
|
|||||||
SetJumpTarget(skip);
|
SetJumpTarget(skip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyPrefixD(dregs, sz);
|
||||||
|
|
||||||
fpr.ReleaseSpillLocks();
|
fpr.ReleaseSpillLocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,6 +1145,10 @@ void Jit::Comp_Vi2f(MIPSOpcode op) {
|
|||||||
|
|
||||||
// Translation of ryg's half_to_float5_SSE2
|
// Translation of ryg's half_to_float5_SSE2
|
||||||
void Jit::Comp_Vh2f(MIPSOpcode op) {
|
void Jit::Comp_Vh2f(MIPSOpcode op) {
|
||||||
|
CONDITIONAL_DISABLE;
|
||||||
|
if (js.HasUnknownPrefix())
|
||||||
|
DISABLE;
|
||||||
|
|
||||||
#define SSE_CONST4(name, val) static const u32 MEMORY_ALIGNED16(name[4]) = { (val), (val), (val), (val) }
|
#define SSE_CONST4(name, val) static const u32 MEMORY_ALIGNED16(name[4]) = { (val), (val), (val), (val) }
|
||||||
|
|
||||||
SSE_CONST4(mask_nosign, 0x7fff);
|
SSE_CONST4(mask_nosign, 0x7fff);
|
||||||
@ -1150,11 +1157,6 @@ void Jit::Comp_Vh2f(MIPSOpcode op) {
|
|||||||
SSE_CONST4(exp_infnan, 255 << 23);
|
SSE_CONST4(exp_infnan, 255 << 23);
|
||||||
|
|
||||||
#undef SSE_CONST4
|
#undef SSE_CONST4
|
||||||
|
|
||||||
CONDITIONAL_DISABLE;
|
|
||||||
if (js.HasUnknownPrefix())
|
|
||||||
DISABLE;
|
|
||||||
|
|
||||||
VectorSize sz = GetVecSize(op);
|
VectorSize sz = GetVecSize(op);
|
||||||
VectorSize outsize;
|
VectorSize outsize;
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
|
@ -243,13 +243,6 @@ void Jit::CompileDelaySlot(int flags, RegCacheState *state)
|
|||||||
LOAD_FLAGS; // restore flag!
|
LOAD_FLAGS; // restore flag!
|
||||||
}
|
}
|
||||||
|
|
||||||
void Jit::CompileAt(u32 addr)
|
|
||||||
{
|
|
||||||
CheckJitBreakpoint(addr, 0);
|
|
||||||
MIPSOpcode op = Memory::Read_Instruction(addr);
|
|
||||||
MIPSCompileOp(op);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Jit::EatInstruction(MIPSOpcode op)
|
void Jit::EatInstruction(MIPSOpcode op)
|
||||||
{
|
{
|
||||||
MIPSInfo info = MIPSGetInfo(op);
|
MIPSInfo info = MIPSGetInfo(op);
|
||||||
|
@ -58,7 +58,8 @@ class Jit : public Gen::XCodeBlock
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Jit(MIPSState *mips);
|
Jit(MIPSState *mips);
|
||||||
~Jit();
|
virtual ~Jit();
|
||||||
|
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
static void DoDummyState(PointerWrap &p);
|
static void DoDummyState(PointerWrap &p);
|
||||||
|
|
||||||
@ -76,7 +77,6 @@ public:
|
|||||||
return asm_.IsInSpace(p);
|
return asm_.IsInSpace(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompileAt(u32 addr);
|
|
||||||
void Comp_RunBlock(MIPSOpcode op);
|
void Comp_RunBlock(MIPSOpcode op);
|
||||||
|
|
||||||
// Ops
|
// Ops
|
||||||
|
@ -150,7 +150,7 @@ Opcode Read_Instruction(u32 address)
|
|||||||
if (MIPS_IS_EMUHACK(inst) && MIPSComp::jit)
|
if (MIPS_IS_EMUHACK(inst) && MIPSComp::jit)
|
||||||
{
|
{
|
||||||
JitBlockCache *bc = MIPSComp::jit->GetBlockCache();
|
JitBlockCache *bc = MIPSComp::jit->GetBlockCache();
|
||||||
int block_num = bc->GetBlockNumberFromEmuHackOp(inst);
|
int block_num = bc->GetBlockNumberFromEmuHackOp(inst, true);
|
||||||
if (block_num >= 0) {
|
if (block_num >= 0) {
|
||||||
return bc->GetOriginalFirstOp(block_num);
|
return bc->GetOriginalFirstOp(block_num);
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user