diff options
Diffstat (limited to 'src/compiler/codegen/mips/MipsRallocUtil.cc')
| -rw-r--r-- | src/compiler/codegen/mips/MipsRallocUtil.cc | 209 |
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 |