mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-25 19:30:53 +00:00
ARMv6 literal pool method.
This commit is contained in:
parent
165cfe53a3
commit
bdfe24a86b
@ -118,6 +118,36 @@ void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
||||
}
|
||||
}
|
||||
|
||||
void ARMXEmitter::FlushLitPool()
|
||||
{
|
||||
for(std::vector<LiteralPool>::iterator it = currentLitPool.begin(); it != currentLitPool.end(); ++it) {
|
||||
LiteralPool item = *it;
|
||||
// Write the constant to Literal Pool
|
||||
Write32(item.val);
|
||||
s32 offset = (s32)code - (s32)item.ldr_address;
|
||||
// Backpatch the LDR
|
||||
code -= offset;
|
||||
LDRLIT(item.reg, abs(offset - 8), offset - 8 > 0);
|
||||
code += offset - 4;
|
||||
}
|
||||
// TODO: Save a copy of previous pools in case they are still in range.
|
||||
currentLitPool.clear();
|
||||
pool_size = 0;
|
||||
}
|
||||
|
||||
void ARMXEmitter::AddNewLit(ArmGen::ARMReg reg, u32 val)
|
||||
{
|
||||
// TODO: Look up current constants,
|
||||
// return that value instead of generating a new one.
|
||||
int index = pool_size++;
|
||||
currentLitPool.push_back();
|
||||
currentLitPool[index].i = pool_size;
|
||||
currentLitPool[index].val = val;
|
||||
currentLitPool[index].reg = reg;
|
||||
currentLitPool[index].ldr_address = (u32)code;
|
||||
Write32(0); // To be backpatched later
|
||||
}
|
||||
|
||||
void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
|
||||
{
|
||||
Operand2 op2;
|
||||
@ -149,23 +179,7 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
|
||||
MOVT(reg, val, true);
|
||||
} else {
|
||||
// ARMv6 - fallback sequence.
|
||||
// TODO: Optimize further. Can for example choose negation etc.
|
||||
// Literal pools is another way to do this but much more complicated
|
||||
// so I can't really be bothered for an outdated CPU architecture like ARMv6.
|
||||
bool first = true;
|
||||
int shift = 16;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (val & 0xFF) {
|
||||
if (first) {
|
||||
MOV(reg, Operand2((u8)val, (u8)(shift & 0xF)));
|
||||
first = false;
|
||||
} else {
|
||||
ORR(reg, reg, Operand2((u8)val, (u8)(shift & 0xF)));
|
||||
}
|
||||
}
|
||||
shift -= 4;
|
||||
val >>= 8;
|
||||
}
|
||||
AddNewLit(reg, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -667,6 +681,8 @@ void ARMXEmitter::LDRSB(ARMReg dest, ARMReg base, ARMReg offset, bool Index, boo
|
||||
{
|
||||
Write32(condition | (0x01 << 20) | (Index << 24) | (Add << 23) | (base << 16) | (dest << 12) | (0xD << 4) | offset);
|
||||
}
|
||||
void ARMXEmitter::LDRLIT (ARMReg dest, u32 offset, bool Add) { Write32(condition | 0x05 << 24 | Add << 23 | 0x1F << 16 | dest << 12 | offset);}
|
||||
|
||||
void ARMXEmitter::WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList)
|
||||
{
|
||||
Write32(condition | (op << 20) | (WriteBack << 21) | (dest << 16) | RegList);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#if defined(__SYMBIAN32__) || defined(PANDORA)
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
#undef _IP
|
||||
#undef R0
|
||||
@ -333,6 +334,14 @@ struct FixupBranch
|
||||
int type; //0 = B 1 = BL
|
||||
};
|
||||
|
||||
struct LiteralPool
|
||||
{
|
||||
int i;
|
||||
u32 ldr_address;
|
||||
u32 val;
|
||||
ArmGen::ARMReg reg;
|
||||
};
|
||||
|
||||
typedef const u8* JumpTarget;
|
||||
|
||||
class ARMXEmitter
|
||||
@ -342,6 +351,8 @@ private:
|
||||
u8 *code, *startcode;
|
||||
u8 *lastCacheFlushEnd;
|
||||
u32 condition;
|
||||
int pool_size;
|
||||
std::vector<LiteralPool> currentLitPool;
|
||||
|
||||
void WriteStoreOp(u32 op, ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void WriteRegStoreOp(u32 op, ARMReg dest, bool WriteBack, u16 RegList);
|
||||
@ -359,7 +370,7 @@ protected:
|
||||
inline void Write32(u32 value) {*(u32*)code = value; code+=4;}
|
||||
|
||||
public:
|
||||
ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0) {
|
||||
ARMXEmitter() : code(0), startcode(0), lastCacheFlushEnd(0), pool_size(0) {
|
||||
condition = CC_AL << 28;
|
||||
}
|
||||
ARMXEmitter(u8 *code_ptr) {
|
||||
@ -367,6 +378,7 @@ public:
|
||||
lastCacheFlushEnd = code_ptr;
|
||||
startcode = code_ptr;
|
||||
condition = CC_AL << 28;
|
||||
pool_size = 0;
|
||||
}
|
||||
virtual ~ARMXEmitter() {}
|
||||
|
||||
@ -379,6 +391,9 @@ public:
|
||||
void FlushIcacheSection(u8 *start, u8 *end);
|
||||
u8 *GetWritableCodePtr();
|
||||
|
||||
void FlushLitPool();
|
||||
void AddNewLit(ArmGen::ARMReg reg, u32 val);
|
||||
|
||||
void SetCC(CCFlags cond = CC_AL);
|
||||
|
||||
// Special purpose instructions
|
||||
@ -490,6 +505,7 @@ public:
|
||||
void LDRSH(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||
void LDRB (ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||
void LDRSB(ARMReg dest, ARMReg base, ARMReg offset, bool Index, bool Add);
|
||||
void LDRLIT(ARMReg dest, u32 offset, bool Add);
|
||||
|
||||
void STR (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
void STRH (ARMReg dest, ARMReg src, Operand2 op2 = 0);
|
||||
|
@ -219,6 +219,7 @@ const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b)
|
||||
js.compilerPC += 4;
|
||||
numInstructions++;
|
||||
}
|
||||
FlushLitPool();
|
||||
#ifdef LOGASM
|
||||
if (logBlocks > 0 && dontLogBlocks == 0) {
|
||||
for (u32 cpc = em_address; cpc != js.compilerPC + 4; cpc += 4) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user