Add MIPS support to pixelflinger.
See the comment-block at the top of MIPSAssembler.cpp for
implementation overview.
Change-Id: Id492c10610574af8c89c38d19e12fafc3652c28a
diff --git a/libpixelflinger/codeflinger/GGLAssembler.cpp b/libpixelflinger/codeflinger/GGLAssembler.cpp
index f1d81b2..1ddf93d 100644
--- a/libpixelflinger/codeflinger/GGLAssembler.cpp
+++ b/libpixelflinger/codeflinger/GGLAssembler.cpp
@@ -31,7 +31,8 @@
// ----------------------------------------------------------------------------
GGLAssembler::GGLAssembler(ARMAssemblerInterface* target)
- : ARMAssemblerProxy(target), RegisterAllocator(), mOptLevel(7)
+ : ARMAssemblerProxy(target),
+ RegisterAllocator(ARMAssemblerProxy::getCodegenArch()), mOptLevel(7)
{
}
@@ -230,7 +231,9 @@
// texel generation
build_textures(parts, regs);
- }
+ if (registerFile().status())
+ return registerFile().status();
+ }
if ((blending & (FACTOR_DST|BLEND_DST)) ||
(mMasking && !mAllMasked) ||
@@ -890,6 +893,15 @@
return;
}
+ if (getCodegenArch() == CODEGEN_ARCH_MIPS) {
+ // MIPS can do 16-bit imm in 1 instr, 32-bit in 3 instr
+ // the below ' while (mask)' code is buggy on mips
+ // since mips returns true on isValidImmediate()
+ // then we get multiple AND instr (positive logic)
+ AND( AL, 0, d, s, imm(mask) );
+ return;
+ }
+
int negative_logic = !isValidImmediate(mask);
if (negative_logic) {
mask = ~mask & size;
@@ -1002,6 +1014,15 @@
// cheezy register allocator...
// ----------------------------------------------------------------------------
+// Modified to support MIPS processors, in a very simple way. We retain the
+// (Arm) limit of 16 total registers, but shift the mapping of those registers
+// from 0-15, to 2-17. Register 0 on Mips cannot be used as GP registers, and
+// register 1 has a traditional use as a temp).
+
+RegisterAllocator::RegisterAllocator(int arch) : mRegs(arch)
+{
+}
+
void RegisterAllocator::reset()
{
mRegs.reset();
@@ -1029,16 +1050,22 @@
// ----------------------------------------------------------------------------
-RegisterAllocator::RegisterFile::RegisterFile()
- : mRegs(0), mTouched(0), mStatus(0)
+RegisterAllocator::RegisterFile::RegisterFile(int codegen_arch)
+ : mRegs(0), mTouched(0), mStatus(0), mArch(codegen_arch), mRegisterOffset(0)
{
+ if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) {
+ mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
+ }
reserve(ARMAssemblerInterface::SP);
reserve(ARMAssemblerInterface::PC);
}
-RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs)
- : mRegs(rhs.mRegs), mTouched(rhs.mTouched)
+RegisterAllocator::RegisterFile::RegisterFile(const RegisterFile& rhs, int codegen_arch)
+ : mRegs(rhs.mRegs), mTouched(rhs.mTouched), mArch(codegen_arch), mRegisterOffset(0)
{
+ if (mArch == ARMAssemblerInterface::CODEGEN_ARCH_MIPS) {
+ mRegisterOffset = 2; // ARM has regs 0..15, MIPS offset to 2..17
+ }
}
RegisterAllocator::RegisterFile::~RegisterFile()
@@ -1057,8 +1084,12 @@
reserve(ARMAssemblerInterface::PC);
}
+// RegisterFile::reserve() take a register parameter in the
+// range 0-15 (Arm compatible), but on a Mips processor, will
+// return the actual allocated register in the range 2-17.
int RegisterAllocator::RegisterFile::reserve(int reg)
{
+ reg += mRegisterOffset;
LOG_ALWAYS_FATAL_IF(isUsed(reg),
"reserving register %d, but already in use",
reg);
@@ -1067,6 +1098,7 @@
return reg;
}
+// This interface uses regMask in range 2-17 on MIPS, no translation.
void RegisterAllocator::RegisterFile::reserveSeveral(uint32_t regMask)
{
mRegs |= regMask;
@@ -1075,7 +1107,7 @@
int RegisterAllocator::RegisterFile::isUsed(int reg) const
{
- LOG_ALWAYS_FATAL_IF(reg>=16, "invalid register %d", reg);
+ LOG_ALWAYS_FATAL_IF(reg>=16+(int)mRegisterOffset, "invalid register %d", reg);
return mRegs & (1<<reg);
}
@@ -1086,10 +1118,10 @@
6, 7, 8, 9,
10, 11 };
const int nbreg = sizeof(priorityList);
- int i, r;
+ int i, r, reg;
for (i=0 ; i<nbreg ; i++) {
r = priorityList[i];
- if (!isUsed(r)) {
+ if (!isUsed(r + mRegisterOffset)) {
break;
}
}
@@ -1102,18 +1134,20 @@
// the code will never be run anyway.
return ARMAssemblerInterface::SP;
}
- reserve(r);
- return r;
+ reg = reserve(r); // Param in Arm range 0-15, returns range 2-17 on Mips.
+ return reg;
}
bool RegisterAllocator::RegisterFile::hasFreeRegs() const
{
- return ((mRegs & 0xFFFF) == 0xFFFF) ? false : true;
+ uint32_t regs = mRegs >> mRegisterOffset; // MIPS fix.
+ return ((regs & 0xFFFF) == 0xFFFF) ? false : true;
}
int RegisterAllocator::RegisterFile::countFreeRegs() const
{
- int f = ~mRegs & 0xFFFF;
+ uint32_t regs = mRegs >> mRegisterOffset; // MIPS fix.
+ int f = ~regs & 0xFFFF;
// now count number of 1
f = (f & 0x5555) + ((f>>1) & 0x5555);
f = (f & 0x3333) + ((f>>2) & 0x3333);
@@ -1124,18 +1158,24 @@
void RegisterAllocator::RegisterFile::recycle(int reg)
{
- LOG_FATAL_IF(!isUsed(reg),
- "recycling unallocated register %d",
- reg);
+ // commented out, since common failure of running out of regs
+ // triggers this assertion. Since the code is not execectued
+ // in that case, it does not matter. No reason to FATAL err.
+ // LOG_FATAL_IF(!isUsed(reg),
+ // "recycling unallocated register %d",
+ // reg);
mRegs &= ~(1<<reg);
}
void RegisterAllocator::RegisterFile::recycleSeveral(uint32_t regMask)
{
- LOG_FATAL_IF((mRegs & regMask)!=regMask,
- "recycling unallocated registers "
- "(recycle=%08x, allocated=%08x, unallocated=%08x)",
- regMask, mRegs, mRegs®Mask);
+ // commented out, since common failure of running out of regs
+ // triggers this assertion. Since the code is not execectued
+ // in that case, it does not matter. No reason to FATAL err.
+ // LOG_FATAL_IF((mRegs & regMask)!=regMask,
+ // "recycling unallocated registers "
+ // "(recycle=%08x, allocated=%08x, unallocated=%08x)",
+ // regMask, mRegs, mRegs®Mask);
mRegs &= ~regMask;
}