mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-03-04 20:27:57 +00:00
Jit unaligned reads/writes.
This mostly just improves perf on debug, not really on the map for release.
This commit is contained in:
parent
bab7947be6
commit
f777c872e6
@ -148,44 +148,70 @@ namespace MIPSComp
|
|||||||
CompITypeMemWrite(op, 32, (void *) &Memory::Write_U32);
|
CompITypeMemWrite(op, 32, (void *) &Memory::Write_U32);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 134: //lwl
|
case 34: //lwl
|
||||||
{
|
{
|
||||||
Crash();
|
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||||
//u32 shift = (addr & 3) << 3;
|
// Looking for lwr rd, offset-3(rs) which makes a pair.
|
||||||
//u32 mem = ReadMem32(addr & 0xfffffffc);
|
u32 desiredOp = ((op + (4 << 26)) & 0xFFFF0000) + (offset - 3);
|
||||||
//R(rt) = ( u32(R(rt)) & (0x00ffffff >> shift) ) | ( mem << (24 - shift) );
|
if (!js.inDelaySlot && nextOp == desiredOp)
|
||||||
|
{
|
||||||
|
EatInstruction(nextOp);
|
||||||
|
// nextOp has the correct address.
|
||||||
|
CompITypeMemRead(nextOp, 32, &XEmitter::MOVZX, (void *) &Memory::Read_U32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Comp_Generic(op);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 138: //lwr
|
case 38: //lwr
|
||||||
{
|
{
|
||||||
Crash();
|
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||||
//u32 shift = (addr & 3) << 3;
|
// Looking for lwl rd, offset+3(rs) which makes a pair.
|
||||||
//u32 mem = ReadMem32(addr & 0xfffffffc);
|
u32 desiredOp = ((op - (4 << 26)) & 0xFFFF0000) + (offset + 3);
|
||||||
|
if (!js.inDelaySlot && nextOp == desiredOp)
|
||||||
//R(rt) = ( u32(rt) & (0xffffff00 << (24 - shift)) ) | ( mem >> shift );
|
{
|
||||||
|
EatInstruction(nextOp);
|
||||||
|
// op has the correct address.
|
||||||
|
CompITypeMemRead(op, 32, &XEmitter::MOVZX, (void *) &Memory::Read_U32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Comp_Generic(op);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 142: //swl
|
case 42: //swl
|
||||||
{
|
{
|
||||||
Crash();
|
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||||
//u32 shift = (addr & 3) << 3;
|
// Looking for swr rd, offset-3(rs) which makes a pair.
|
||||||
//u32 mem = ReadMem32(addr & 0xfffffffc);
|
u32 desiredOp = ((op + (4 << 26)) & 0xFFFF0000) + (offset - 3);
|
||||||
//WriteMem32((addr & 0xfffffffc), ( ( u32(R(rt)) >> (24 - shift) ) ) |
|
if (!js.inDelaySlot && nextOp == desiredOp)
|
||||||
// ( mem & (0xffffff00 << shift) ));
|
{
|
||||||
|
EatInstruction(nextOp);
|
||||||
|
// nextOp has the correct address.
|
||||||
|
CompITypeMemWrite(nextOp, 32, (void *) &Memory::Write_U32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Comp_Generic(op);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 146: //swr
|
|
||||||
|
case 46: //swr
|
||||||
{
|
{
|
||||||
Crash();
|
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
|
||||||
// u32 shift = (addr & 3) << 3;
|
// Looking for swl rd, offset+3(rs) which makes a pair.
|
||||||
// u32 mem = ReadMem32(addr & 0xfffffffc);
|
u32 desiredOp = ((op - (4 << 26)) & 0xFFFF0000) + (offset + 3);
|
||||||
//
|
if (!js.inDelaySlot && nextOp == desiredOp)
|
||||||
// WriteMem32((addr & 0xfffffffc), ( ( u32(R(rt)) << shift ) |
|
{
|
||||||
// (mem & (0x00ffffff >> (24 - shift)) ) ) );
|
EatInstruction(nextOp);
|
||||||
|
// op has the correct address.
|
||||||
|
CompITypeMemWrite(op, 32, (void *) &Memory::Write_U32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Comp_Generic(op);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Comp_Generic(op);
|
Comp_Generic(op);
|
||||||
return ;
|
return ;
|
||||||
|
@ -158,6 +158,18 @@ void Jit::CompileAt(u32 addr)
|
|||||||
MIPSCompileOp(op);
|
MIPSCompileOp(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Jit::EatInstruction(u32 op)
|
||||||
|
{
|
||||||
|
u32 info = MIPSGetInfo(op);
|
||||||
|
_dbg_assert_msg_(JIT, !(info & DELAYSLOT), "Never eat a branch op.");
|
||||||
|
_dbg_assert_msg_(JIT, !js.inDelaySlot, "Never eat an instruction inside a delayslot.");
|
||||||
|
|
||||||
|
CheckJitBreakpoint(js.compilerPC + 4, 0);
|
||||||
|
js.numInstructions++;
|
||||||
|
js.compilerPC += 4;
|
||||||
|
js.downcountAmount += MIPSGetInstructionCycleEstimate(op);
|
||||||
|
}
|
||||||
|
|
||||||
void Jit::Compile(u32 em_address)
|
void Jit::Compile(u32 em_address)
|
||||||
{
|
{
|
||||||
if (GetSpaceLeft() < 0x10000 || blocks.IsFull())
|
if (GetSpaceLeft() < 0x10000 || blocks.IsFull())
|
||||||
@ -203,7 +215,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
|
|||||||
gpr.Start(mips_, analysis);
|
gpr.Start(mips_, analysis);
|
||||||
fpr.Start(mips_, analysis);
|
fpr.Start(mips_, analysis);
|
||||||
|
|
||||||
int numInstructions = 0;
|
js.numInstructions = 0;
|
||||||
while (js.compiling)
|
while (js.compiling)
|
||||||
{
|
{
|
||||||
// Jit breakpoints are quite fast, so let's do them in release too.
|
// Jit breakpoints are quite fast, so let's do them in release too.
|
||||||
@ -215,13 +227,13 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
|
|||||||
MIPSCompileOp(inst);
|
MIPSCompileOp(inst);
|
||||||
|
|
||||||
js.compilerPC += 4;
|
js.compilerPC += 4;
|
||||||
numInstructions++;
|
js.numInstructions++;
|
||||||
}
|
}
|
||||||
|
|
||||||
b->codeSize = (u32)(GetCodePtr() - b->normalEntry);
|
b->codeSize = (u32)(GetCodePtr() - b->normalEntry);
|
||||||
NOP();
|
NOP();
|
||||||
AlignCode4();
|
AlignCode4();
|
||||||
b->originalSize = numInstructions;
|
b->originalSize = js.numInstructions;
|
||||||
return b->normalEntry;
|
return b->normalEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ struct JitState
|
|||||||
bool cancel;
|
bool cancel;
|
||||||
bool inDelaySlot;
|
bool inDelaySlot;
|
||||||
int downcountAmount;
|
int downcountAmount;
|
||||||
|
int numInstructions;
|
||||||
bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block
|
bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block
|
||||||
JitBlock *curBlock;
|
JitBlock *curBlock;
|
||||||
|
|
||||||
@ -107,8 +108,6 @@ public:
|
|||||||
void Compile(u32 em_address); // Compiles a block at current MIPS PC
|
void Compile(u32 em_address); // Compiles a block at current MIPS PC
|
||||||
const u8 *DoJit(u32 em_address, JitBlock *b);
|
const u8 *DoJit(u32 em_address, JitBlock *b);
|
||||||
|
|
||||||
// See CompileDelaySlotFlags for flags.
|
|
||||||
void CompileDelaySlot(int flags);
|
|
||||||
void CompileAt(u32 addr);
|
void CompileAt(u32 addr);
|
||||||
void Comp_RunBlock(u32 op);
|
void Comp_RunBlock(u32 op);
|
||||||
|
|
||||||
@ -151,6 +150,10 @@ private:
|
|||||||
void FlushAll();
|
void FlushAll();
|
||||||
void WriteDowncount(int offset = 0);
|
void WriteDowncount(int offset = 0);
|
||||||
|
|
||||||
|
// See CompileDelaySlotFlags for flags.
|
||||||
|
void CompileDelaySlot(int flags);
|
||||||
|
void EatInstruction(u32 op);
|
||||||
|
|
||||||
void WriteExit(u32 destination, int exit_num);
|
void WriteExit(u32 destination, int exit_num);
|
||||||
void WriteExitDestInEAX();
|
void WriteExitDestInEAX();
|
||||||
// void WriteRfiExitDestInEAX();
|
// void WriteRfiExitDestInEAX();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user