summaryrefslogtreecommitdiff
path: root/src/compiler/codegen/mips/MipsRallocUtil.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/codegen/mips/MipsRallocUtil.cc')
-rw-r--r--src/compiler/codegen/mips/MipsRallocUtil.cc209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/compiler/codegen/mips/MipsRallocUtil.cc b/src/compiler/codegen/mips/MipsRallocUtil.cc
new file mode 100644
index 0000000000..a243415ed1
--- /dev/null
+++ b/src/compiler/codegen/mips/MipsRallocUtil.cc
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This file contains Mips-specific register allocation support.
+ */
+
+#include "../../CompilerUtility.h"
+#include "../../CompilerIR.h"
+#include "../..//Dataflow.h"
+#include "MipsLIR.h"
+#include "Codegen.h"
+#include "../Ralloc.h"
+
+namespace art {
+
+/*
+ * Mark a callee-save fp register as promoted. Note that
+ * vpush/vpop uses contiguous register lists so we must
+ * include any holes in the mask. Associate holes with
+ * Dalvik register INVALID_VREG (0xFFFFU).
+ */
+STATIC void markPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
+{
+ UNIMPLEMENTED(FATAL) << "No support yet for promoted FP regs";
+#if 0
+ DCHECK_GE(reg, FP_REG_MASK + FP_CALLEE_SAVE_BASE);
+ reg = (reg & FP_REG_MASK) - FP_CALLEE_SAVE_BASE;
+ // Ensure fpVmapTable is large enough
+ int tableSize = cUnit->fpVmapTable.size();
+ for (int i = tableSize; i < (reg + 1); i++) {
+ cUnit->fpVmapTable.push_back(INVALID_VREG);
+ }
+ // Add the current mapping
+ cUnit->fpVmapTable[reg] = sReg;
+ // Size of fpVmapTable is high-water mark, use to set mask
+ cUnit->numFPSpills = cUnit->fpVmapTable.size();
+ cUnit->fpSpillMask = ((1 << cUnit->numFPSpills) - 1) << FP_CALLEE_SAVE_BASE;
+#endif
+}
+
+void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
+{
+ RegisterInfo* info1 = oatGetRegInfo(cUnit, reg1);
+ RegisterInfo* info2 = oatGetRegInfo(cUnit, reg2);
+ DCHECK(info1 && info2 && info1->pair && info2->pair &&
+ (info1->partner == info2->reg) &&
+ (info2->partner == info1->reg));
+ if ((info1->live && info1->dirty) || (info2->live && info2->dirty)) {
+ if (!(info1->isTemp && info2->isTemp)) {
+ /* Should not happen. If it does, there's a problem in evalLoc */
+ LOG(FATAL) << "Long half-temp, half-promoted";
+ }
+
+ info1->dirty = false;
+ info2->dirty = false;
+ if (oatS2VReg(cUnit, info2->sReg) <
+ oatS2VReg(cUnit, info1->sReg))
+ info1 = info2;
+ int vReg = oatS2VReg(cUnit, info1->sReg);
+ oatFlushRegWideImpl(cUnit, rSP,
+ oatVRegOffset(cUnit, vReg),
+ info1->reg, info1->partner);
+ }
+}
+
+void oatFlushReg(CompilationUnit* cUnit, int reg)
+{
+ RegisterInfo* info = oatGetRegInfo(cUnit, reg);
+ if (info->live && info->dirty) {
+ info->dirty = false;
+ int vReg = oatS2VReg(cUnit, info->sReg);
+ oatFlushRegImpl(cUnit, rSP,
+ oatVRegOffset(cUnit, vReg),
+ reg, kWord);
+ }
+}
+
+/* Give access to the target-dependent FP register encoding to common code */
+bool oatIsFpReg(int reg) {
+ return FPREG(reg);
+}
+
+uint32_t oatFpRegMask() {
+ return FP_REG_MASK;
+}
+
+/* Clobber all regs that might be used by an external C call */
+extern void oatClobberCalleeSave(CompilationUnit *cUnit)
+{
+ oatClobber(cUnit, r_ZERO);
+ oatClobber(cUnit, r_AT);
+ oatClobber(cUnit, r_V0);
+ oatClobber(cUnit, r_V1);
+ oatClobber(cUnit, r_A0);
+ oatClobber(cUnit, r_A1);
+ oatClobber(cUnit, r_A2);
+ oatClobber(cUnit, r_A3);
+ oatClobber(cUnit, r_T0);
+ oatClobber(cUnit, r_T1);
+ oatClobber(cUnit, r_T2);
+ oatClobber(cUnit, r_T3);
+ oatClobber(cUnit, r_T4);
+ oatClobber(cUnit, r_T5);
+ oatClobber(cUnit, r_T6);
+ oatClobber(cUnit, r_T7);
+ oatClobber(cUnit, r_T8);
+ oatClobber(cUnit, r_T9);
+ oatClobber(cUnit, r_K0);
+ oatClobber(cUnit, r_K1);
+ oatClobber(cUnit, r_GP);
+ oatClobber(cUnit, r_FP);
+ oatClobber(cUnit, r_RA);
+ oatClobber(cUnit, r_HI);
+ oatClobber(cUnit, r_LO);
+ oatClobber(cUnit, r_F0);
+ oatClobber(cUnit, r_F1);
+ oatClobber(cUnit, r_F2);
+ oatClobber(cUnit, r_F3);
+ oatClobber(cUnit, r_F4);
+ oatClobber(cUnit, r_F5);
+ oatClobber(cUnit, r_F6);
+ oatClobber(cUnit, r_F7);
+ oatClobber(cUnit, r_F8);
+ oatClobber(cUnit, r_F9);
+ oatClobber(cUnit, r_F10);
+ oatClobber(cUnit, r_F11);
+ oatClobber(cUnit, r_F12);
+ oatClobber(cUnit, r_F13);
+ oatClobber(cUnit, r_F14);
+ oatClobber(cUnit, r_F15);
+}
+
+extern RegLocation oatGetReturnWide(CompilationUnit* cUnit)
+{
+ RegLocation res = LOC_C_RETURN_WIDE;
+ oatClobber(cUnit, r_V0);
+ oatClobber(cUnit, r_V1);
+ oatMarkInUse(cUnit, r_V0);
+ oatMarkInUse(cUnit, r_V1);
+ oatMarkPair(cUnit, res.lowReg, res.highReg);
+ return res;
+}
+
+extern RegLocation oatGetReturnWideAlt(CompilationUnit* cUnit)
+{
+ RegLocation res = LOC_C_RETURN_WIDE_ALT;
+ oatClobber(cUnit, r_F0);
+ oatClobber(cUnit, r_F1);
+ oatMarkInUse(cUnit, r_F0);
+ oatMarkInUse(cUnit, r_F1);
+ oatMarkPair(cUnit, res.lowReg, res.highReg);
+ return res;
+}
+
+extern RegLocation oatGetReturn(CompilationUnit* cUnit)
+{
+ RegLocation res = LOC_C_RETURN;
+ oatClobber(cUnit, r_V0);
+ oatMarkInUse(cUnit, r_V0);
+ return res;
+}
+
+extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit)
+{
+ RegLocation res = LOC_C_RETURN_ALT;
+ oatClobber(cUnit, r_F0);
+ oatMarkInUse(cUnit, r_F0);
+ return res;
+}
+
+extern RegisterInfo* oatGetRegInfo(CompilationUnit* cUnit, int reg)
+{
+ return FPREG(reg) ? &cUnit->regPool->FPRegs[reg & FP_REG_MASK]
+ : &cUnit->regPool->coreRegs[reg];
+}
+
+/* To be used when explicitly managing register use */
+extern void oatLockCallTemps(CompilationUnit* cUnit)
+{
+ oatLockTemp(cUnit, r_A0);
+ oatLockTemp(cUnit, r_A1);
+ oatLockTemp(cUnit, r_A2);
+ oatLockTemp(cUnit, r_A3);
+}
+
+/* To be used when explicitly managing register use */
+extern void oatFreeCallTemps(CompilationUnit* cUnit)
+{
+ oatFreeTemp(cUnit, r_A0);
+ oatFreeTemp(cUnit, r_A1);
+ oatFreeTemp(cUnit, r_A2);
+ oatFreeTemp(cUnit, r_A3);
+}
+
+} // namespace art