Skip to content

Commit

Permalink
Use binary search to find IR block offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Jun 4, 2024
1 parent c22adcf commit 69d618f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
35 changes: 33 additions & 2 deletions Core/MIPS/IR/IRJit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,8 @@ void IRJit::RunLoopUntil(u64 globalticks) {
while (mips->downcount >= 0) {
u32 inst = Memory::ReadUnchecked_U32(mips->pc);
u32 opcode = inst & 0xFF000000;
u32 offset = inst & 0x00FFFFFF;
if (opcode == MIPS_EMUHACK_OPCODE) {
u32 offset = inst & 0x00FFFFFF; // Alternatively, inst - opcode
mips->pc = IRInterpret(mips, blocks_.GetArenaPtr() + offset);
// Note: this will "jump to zero" on a badly constructed block missing exits.
if (!Memory::IsValid4AlignedAddress(mips->pc)) {
Expand Down Expand Up @@ -297,13 +297,43 @@ void IRBlockCache::Clear() {
arena_.shrink_to_fit();
}

IRBlockCache::IRBlockCache() {
// For whatever reason, this makes things go slower?? Probably just a CPU cache alignment fluke.
// arena_.reserve(1024 * 1024 * 2);
}

int IRBlockCache::GetBlockNumFromOffset(int offset) const {
// Block offsets are always in rising order (we don't go back and replace them when invalidated). So we can binary search.
int low = 0;
int high = (int)blocks_.size() - 1;
int found = -1;
while (low <= high) {
int mid = low + (high - low) / 2;
const int blockOffset = blocks_[mid].GetInstructionOffset();
if (blockOffset == offset) {
found = mid;
break;
}
if (blockOffset < offset) {
low = mid + 1;
} else {
high = mid - 1;
}
}

#ifndef _DEBUG
// Then, in debug builds, cross check the result.
return found;
#else
// TODO: Optimize if we need to call this often.
for (int i = 0; i < (int)blocks_.size(); i++) {
if (blocks_[i].GetInstructionOffset() == offset) {
_dbg_assert_(i == found);
return i;
}
}
#endif
_dbg_assert_(found == -1);
return -1;
}

Expand Down Expand Up @@ -377,12 +407,13 @@ int IRBlockCache::FindByCookie(int cookie) {
if (blocks_[0].GetTargetOffset() < 0)
return GetBlockNumFromOffset(cookie);

// TODO: Now that we are using offsets in pure IR mode too, we can probably unify
// the two paradigms. Or actually no, we still need two offsets..
for (int i = 0; i < GetNumBlocks(); ++i) {
int offset = blocks_[i].GetTargetOffset();
if (offset == cookie)
return i;
}

return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion Core/MIPS/IR/IRJit.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class IRBlock {

class IRBlockCache : public JitBlockCacheDebugInterface {
public:
IRBlockCache() {}
IRBlockCache();
void Clear();
std::vector<int> FindInvalidatedBlockNumbers(u32 address, u32 length);
void FinalizeBlock(int blockNum, bool preload = false);
Expand Down
3 changes: 2 additions & 1 deletion GPU/Common/VertexDecoderCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ void VertexDecoder::Step_Color5551() const
u8 *c = decoded_ + decFmt.c0off;
u16 cdata = *(const u16_le *)(ptr_ + coloff);
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && (cdata >> 15) != 0;

c[0] = Convert5To8(cdata & 0x1f);
c[1] = Convert5To8((cdata >> 5) & 0x1f);
c[2] = Convert5To8((cdata >> 10) & 0x1f);
Expand Down Expand Up @@ -558,7 +559,7 @@ void VertexDecoder::Step_Color565Morph() const
c[i] = clamp_u8((int)col[i]);
}
c[3] = 255;
// Always full alpha.
// Always full alpha. (Is this true??)
}

void VertexDecoder::Step_Color5551Morph() const
Expand Down

0 comments on commit 69d618f

Please sign in to comment.