/* * 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 { /* * TUNING: is leaf? Can't just use "hasInvoke" to determine as some * instructions might call out to C/assembly helper functions. Until * machinery is in place, always spill lr. */ void oatAdjustSpillMask(CompilationUnit* cUnit) { cUnit->coreSpillMask |= (1 << r_RA); cUnit->numCoreSpills++; } /* * 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). */ void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg) { LOG(FATAL) << "No support yet for promoted FP regs"; } 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 (SRegToVReg(cUnit, info2->sReg) < SRegToVReg(cUnit, info1->sReg)) info1 = info2; int vReg = SRegToVReg(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 = SRegToVReg(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_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 oatGetReturnWideAlt(CompilationUnit* cUnit) { UNIMPLEMENTED(FATAL) << "No oatGetReturnWideAlt for MIPS"; RegLocation res = LOC_C_RETURN_WIDE; return res; } extern RegLocation oatGetReturnAlt(CompilationUnit* cUnit) { UNIMPLEMENTED(FATAL) << "No oatGetReturnAlt for MIPS"; RegLocation res = LOC_C_RETURN; 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, rARG0); oatLockTemp(cUnit, rARG1); oatLockTemp(cUnit, rARG2); oatLockTemp(cUnit, rARG3); } /* To be used when explicitly managing register use */ extern void oatFreeCallTemps(CompilationUnit* cUnit) { oatFreeTemp(cUnit, rARG0); oatFreeTemp(cUnit, rARG1); oatFreeTemp(cUnit, rARG2); oatFreeTemp(cUnit, rARG3); } /* Convert an instruction to a NOP */ void oatNopLIR( LIR* lir) { ((LIR*)lir)->flags.isNop = true; } } // namespace art