int_arm.cc revision 1bc37c60da71c923ea9a2e99d31ba1b3d76d79a8
1efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 2efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Copyright (C) 2011 The Android Open Source Project 3efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 4efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Licensed under the Apache License, Version 2.0 (the "License"); 5efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * you may not use this file except in compliance with the License. 6efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * You may obtain a copy of the License at 7efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 8efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * http://www.apache.org/licenses/LICENSE-2.0 9efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 10efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Unless required by applicable law or agreed to in writing, software 11efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * distributed under the License is distributed on an "AS IS" BASIS, 12efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * See the License for the specific language governing permissions and 14efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * limitations under the License. 15efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 16efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 17efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* This file contains codegen for the Thumb2 ISA. */ 18efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 19efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#include "oat_compilation_unit.h" 20efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#include "oat/runtime/oat_support_entrypoints.h" 211bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "arm_lir.h" 221bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../codegen_util.h" 231bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee#include "../ralloc_util.h" 24efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 25efc6369224b036a1fb77849f7ae65b3492c832c0buzbeenamespace art { 26efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 27efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, 28efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int src2, LIR* target) 29efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 30efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, src1, src2); 31efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return opCondBranch(cUnit, cond, target); 32efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 33efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 34efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 35efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a Thumb2 IT instruction, which can nullify up to 36efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * four subsequent instructions based on a condition and its 37efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * inverse. The condition applies to the first instruction, which 38efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is executed if the condition is met. The string "guide" consists 39efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * of 0 to 3 chars, and applies to the 2nd through 4th instruction. 40efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * A "T" means the instruction is executed if the condition is 41efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * met, and an "E" means the instruction is executed if the condition 42efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is not met. 43efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 44efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opIT(CompilationUnit* cUnit, ArmConditionCode code, const char* guide) 45efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 46efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int mask; 47efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int condBit = code & 1; 48efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int altBit = condBit ^ 1; 49efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int mask3 = 0; 50efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int mask2 = 0; 51efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int mask1 = 0; 52efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 53efc6369224b036a1fb77849f7ae65b3492c832c0buzbee //Note: case fallthroughs intentional 54efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch (strlen(guide)) { 55efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 3: 56efc6369224b036a1fb77849f7ae65b3492c832c0buzbee mask1 = (guide[2] == 'T') ? condBit : altBit; 57efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 2: 58efc6369224b036a1fb77849f7ae65b3492c832c0buzbee mask2 = (guide[1] == 'T') ? condBit : altBit; 59efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 1: 60efc6369224b036a1fb77849f7ae65b3492c832c0buzbee mask3 = (guide[0] == 'T') ? condBit : altBit; 61efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 62efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case 0: 63efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 64efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 65efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "OAT: bad case in opIT"; 66efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 67efc6369224b036a1fb77849f7ae65b3492c832c0buzbee mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) | 68efc6369224b036a1fb77849f7ae65b3492c832c0buzbee (1 << (3 - strlen(guide))); 69efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return newLIR2(cUnit, kThumb2It, code, mask); 70efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 71efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 72efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 73efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * 64-bit 3way compare function. 74efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * mov rX, #-1 75efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * cmp op1hi, op2hi 76efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * blt done 77efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * bgt flip 78efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * sub rX, op1lo, op2lo (treat as unsigned) 79efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * beq done 80efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * ite hi 81efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * mov(hi) rX, #-1 82efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * mov(!hi) rX, #1 83efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * flip: 84efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * neg rX 85efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * done: 86efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 87efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genCmpLong(CompilationUnit* cUnit, RegLocation rlDest, 88efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1, RegLocation rlSrc2) 89efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 90efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* target1; 91efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* target2; 92efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); 93efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 94efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int tReg = oatAllocTemp(cUnit); 95efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loadConstant(cUnit, tReg, -1); 96efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); 97efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* branch1 = opCondBranch(cUnit, kCondLt, NULL); 98efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* branch2 = opCondBranch(cUnit, kCondGt, NULL); 99efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegReg(cUnit, kOpSub, tReg, rlSrc1.lowReg, rlSrc2.lowReg); 100efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* branch3 = opCondBranch(cUnit, kCondEq, NULL); 101efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 102efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opIT(cUnit, kArmCondHi, "E"); 103efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR2(cUnit, kThumb2MovImmShift, tReg, modifiedImmediate(-1)); 104efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loadConstant(cUnit, tReg, 1); 105efc6369224b036a1fb77849f7ae65b3492c832c0buzbee genBarrier(cUnit); 106efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 107efc6369224b036a1fb77849f7ae65b3492c832c0buzbee target2 = newLIR0(cUnit, kPseudoTargetLabel); 108efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpNeg, tReg, tReg); 109efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 110efc6369224b036a1fb77849f7ae65b3492c832c0buzbee target1 = newLIR0(cUnit, kPseudoTargetLabel); 111efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 112efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlTemp = locCReturn(); // Just using as template, will change 113efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlTemp.lowReg = tReg; 114efc6369224b036a1fb77849f7ae65b3492c832c0buzbee storeValue(cUnit, rlDest, rlTemp); 115efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, tReg); 116efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 117cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee branch1->target = target1; 118cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee branch2->target = target2; 119efc6369224b036a1fb77849f7ae65b3492c832c0buzbee branch3->target = branch1->target; 120efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 121efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 122efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genFusedLongCmpBranch(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) 123efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 124efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* labelList = cUnit->blockLabelList; 125efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* taken = &labelList[bb->taken->id]; 126efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* notTaken = &labelList[bb->fallThrough->id]; 127efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1 = oatGetSrcWide(cUnit, mir, 0); 128efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc2 = oatGetSrcWide(cUnit, mir, 2); 129efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); 130efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); 131efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); 132efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg); 133efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch(ccode) { 134efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kCondEq: 135efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondNe, notTaken); 136efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 137efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kCondNe: 138efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondNe, taken); 139efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 140efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kCondLt: 141efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondLt, taken); 142efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondGt, notTaken); 143efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ccode = kCondCc; 144efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 145efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kCondLe: 146efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondLt, taken); 147efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondGt, notTaken); 148efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ccode = kCondLs; 149efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 150efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kCondGt: 151efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondGt, taken); 152efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondLt, notTaken); 153efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ccode = kCondHi; 154efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 155efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case kCondGe: 156efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondGt, taken); 157efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, kCondLt, notTaken); 158efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ccode = kCondCs; 159efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 160efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 161cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(FATAL) << "Unexpected ccode: " << ccode; 162efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 163efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); 164efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opCondBranch(cUnit, ccode, taken); 165efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 166efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 167efc6369224b036a1fb77849f7ae65b3492c832c0buzbee/* 168efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * Generate a register comparison to an immediate and branch. Caller 169efc6369224b036a1fb77849f7ae65b3492c832c0buzbee * is responsible for setting branch target field. 170efc6369224b036a1fb77849f7ae65b3492c832c0buzbee */ 171efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg, 172efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int checkValue, LIR* target) 173efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 174efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* branch; 175efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int modImm; 176efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ArmConditionCode armCond = oatArmConditionEncoding(cond); 177efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if ((ARM_LOWREG(reg)) && (checkValue == 0) && 178efc6369224b036a1fb77849f7ae65b3492c832c0buzbee ((armCond == kArmCondEq) || (armCond == kArmCondNe))) { 179efc6369224b036a1fb77849f7ae65b3492c832c0buzbee branch = newLIR2(cUnit, (armCond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, 180efc6369224b036a1fb77849f7ae65b3492c832c0buzbee reg, 0); 181efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 182efc6369224b036a1fb77849f7ae65b3492c832c0buzbee modImm = modifiedImmediate(checkValue); 183efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (ARM_LOWREG(reg) && ((checkValue & 0xff) == checkValue)) { 184efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR2(cUnit, kThumbCmpRI8, reg, checkValue); 185efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else if (modImm >= 0) { 186efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR2(cUnit, kThumb2CmpRI8, reg, modImm); 187efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 188efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int tReg = oatAllocTemp(cUnit); 189efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loadConstant(cUnit, tReg, checkValue); 190efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, reg, tReg); 191efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 192efc6369224b036a1fb77849f7ae65b3492c832c0buzbee branch = newLIR2(cUnit, kThumbBCond, 0, armCond); 193efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 194efc6369224b036a1fb77849f7ae65b3492c832c0buzbee branch->target = target; 195efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return branch; 196efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 197efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc) 198efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 199efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* res; 200efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int opcode; 201efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (ARM_FPREG(rDest) || ARM_FPREG(rSrc)) 202efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return fpRegCopy(cUnit, rDest, rSrc); 203efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (ARM_LOWREG(rDest) && ARM_LOWREG(rSrc)) 204efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opcode = kThumbMovRR; 205efc6369224b036a1fb77849f7ae65b3492c832c0buzbee else if (!ARM_LOWREG(rDest) && !ARM_LOWREG(rSrc)) 206efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opcode = kThumbMovRR_H2H; 207efc6369224b036a1fb77849f7ae65b3492c832c0buzbee else if (ARM_LOWREG(rDest)) 208efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opcode = kThumbMovRR_H2L; 209efc6369224b036a1fb77849f7ae65b3492c832c0buzbee else 210efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opcode = kThumbMovRR_L2H; 211efc6369224b036a1fb77849f7ae65b3492c832c0buzbee res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); 212efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (!(cUnit->disableOpt & (1 << kSafeOptimizations)) && rDest == rSrc) { 213efc6369224b036a1fb77849f7ae65b3492c832c0buzbee res->flags.isNop = true; 214efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 215efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 216efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 217efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 218efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opRegCopy(CompilationUnit* cUnit, int rDest, int rSrc) 219efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 220efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LIR* res = opRegCopyNoInsert(cUnit, rDest, rSrc); 221cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee oatAppendLIR(cUnit, res); 222efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return res; 223efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 224efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 225efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid opRegCopyWide(CompilationUnit* cUnit, int destLo, int destHi, 226efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int srcLo, int srcHi) 227efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 228efc6369224b036a1fb77849f7ae65b3492c832c0buzbee bool destFP = ARM_FPREG(destLo) && ARM_FPREG(destHi); 229efc6369224b036a1fb77849f7ae65b3492c832c0buzbee bool srcFP = ARM_FPREG(srcLo) && ARM_FPREG(srcHi); 230efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_EQ(ARM_FPREG(srcLo), ARM_FPREG(srcHi)); 231efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_EQ(ARM_FPREG(destLo), ARM_FPREG(destHi)); 232efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (destFP) { 233efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (srcFP) { 234efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegCopy(cUnit, s2d(destLo, destHi), s2d(srcLo, srcHi)); 235efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 236efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR3(cUnit, kThumb2Fmdrr, s2d(destLo, destHi), srcLo, srcHi); 237efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 238efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 239efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (srcFP) { 240efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR3(cUnit, kThumb2Fmrrd, destLo, destHi, s2d(srcLo, srcHi)); 241efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 242efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Handle overlap 243efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (srcHi == destLo) { 244efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegCopy(cUnit, destHi, srcHi); 245efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegCopy(cUnit, destLo, srcLo); 246efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 247efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegCopy(cUnit, destLo, srcLo); 248efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegCopy(cUnit, destHi, srcHi); 249efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 250efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 251efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 252efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 253efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 254efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Table of magic divisors 255efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestruct MagicTable { 256efc6369224b036a1fb77849f7ae65b3492c832c0buzbee uint32_t magic; 257efc6369224b036a1fb77849f7ae65b3492c832c0buzbee uint32_t shift; 258efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DividePattern pattern; 259efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 260efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 261efc6369224b036a1fb77849f7ae65b3492c832c0buzbeestatic const MagicTable magicTable[] = { 262efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0, 0, DivideNone}, // 0 263efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0, 0, DivideNone}, // 1 264efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0, 0, DivideNone}, // 2 265efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x55555556, 0, Divide3}, // 3 266efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0, 0, DivideNone}, // 4 267efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x66666667, 1, Divide5}, // 5 268efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x2AAAAAAB, 0, Divide3}, // 6 269efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x92492493, 2, Divide7}, // 7 270efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0, 0, DivideNone}, // 8 271efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x38E38E39, 1, Divide5}, // 9 272efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x66666667, 2, Divide5}, // 10 273efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x2E8BA2E9, 1, Divide5}, // 11 274efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x2AAAAAAB, 1, Divide5}, // 12 275efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x4EC4EC4F, 2, Divide5}, // 13 276efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x92492493, 3, Divide7}, // 14 277efc6369224b036a1fb77849f7ae65b3492c832c0buzbee {0x88888889, 3, Divide7}, // 15 278efc6369224b036a1fb77849f7ae65b3492c832c0buzbee}; 279efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 280efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Integer division by constant via reciprocal multiply (Hacker's Delight, 10-4) 281efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool smallLiteralDivide(CompilationUnit* cUnit, Instruction::Code dalvikOpcode, 282efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc, RegLocation rlDest, int lit) 283efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 284cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee if ((lit < 0) || (lit >= static_cast<int>(sizeof(magicTable)/sizeof(magicTable[0])))) { 285efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 286efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 287efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DividePattern pattern = magicTable[lit].pattern; 288efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (pattern == DivideNone) { 289efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 290efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 291efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Tuning: add rem patterns 292efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (dalvikOpcode != Instruction::DIV_INT_LIT8) { 293efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 294efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 295efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 296efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int rMagic = oatAllocTemp(cUnit); 297efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loadConstant(cUnit, rMagic, magicTable[lit].magic); 298efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc = loadValue(cUnit, rlSrc, kCoreReg); 299efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); 300efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int rHi = oatAllocTemp(cUnit); 301efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int rLo = oatAllocTemp(cUnit); 302efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR4(cUnit, kThumb2Smull, rLo, rHi, rMagic, rlSrc.lowReg); 303efc6369224b036a1fb77849f7ae65b3492c832c0buzbee switch(pattern) { 304efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case Divide3: 305efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegRegShift(cUnit, kOpSub, rlResult.lowReg, rHi, 306efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc.lowReg, encodeShift(kArmAsr, 31)); 307efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 308efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case Divide5: 309efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31); 310efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi, 311efc6369224b036a1fb77849f7ae65b3492c832c0buzbee encodeShift(kArmAsr, magicTable[lit].shift)); 312efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 313efc6369224b036a1fb77849f7ae65b3492c832c0buzbee case Divide7: 314efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpAdd, rHi, rlSrc.lowReg); 315efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegImm(cUnit, kOpAsr, rLo, rlSrc.lowReg, 31); 316efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegRegShift(cUnit, kOpRsub, rlResult.lowReg, rLo, rHi, 317efc6369224b036a1fb77849f7ae65b3492c832c0buzbee encodeShift(kArmAsr, magicTable[lit].shift)); 318efc6369224b036a1fb77849f7ae65b3492c832c0buzbee break; 319efc6369224b036a1fb77849f7ae65b3492c832c0buzbee default: 320cbd6d44c0a94f3d26671b5325aa21bbf1335ffe8buzbee LOG(FATAL) << "Unexpected pattern: " << pattern; 321efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 322efc6369224b036a1fb77849f7ae65b3492c832c0buzbee storeValue(cUnit, rlDest, rlResult); 323efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return true; 324efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 325efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 326efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* genRegMemCheck(CompilationUnit* cUnit, ConditionCode cCode, 327efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int reg1, int base, int offset, ThrowKind kind) 328efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 329efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genRegMemCheck for Arm"; 330efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return NULL; 331efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 332efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 333efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeRegLocation genDivRemLit(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int lit, bool isDiv) 334efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 335efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genDivRemLit for Arm"; 336efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return rlDest; 337efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 338efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 339efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeRegLocation genDivRem(CompilationUnit* cUnit, RegLocation rlDest, int reg1, int reg2, bool isDiv) 340efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 341efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genDivRem for Arm"; 342efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return rlDest; 343efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 344efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 345efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) 346efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 347efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_EQ(cUnit->instructionSet, kThumb2); 348efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1 = info->args[0]; 349efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc2 = info->args[1]; 350efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg); 351efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg); 352efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlDest = inlineTarget(cUnit, info); 353efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); 354efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg); 355efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E"); 356efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg); 357efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg); 358efc6369224b036a1fb77849f7ae65b3492c832c0buzbee genBarrier(cUnit); 359efc6369224b036a1fb77849f7ae65b3492c832c0buzbee storeValue(cUnit, rlDest, rlResult); 360efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return true; 361efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 362efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 363efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid opLea(CompilationUnit* cUnit, int rBase, int reg1, int reg2, int scale, int offset) 364efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 365efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of opLea for Arm"; 366efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 367efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 368efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid opTlsCmp(CompilationUnit* cUnit, int offset, int val) 369efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 370efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of opTlsCmp for Arm"; 371efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 372efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 373efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genInlinedCas32(CompilationUnit* cUnit, CallInfo* info, bool need_write_barrier) { 374efc6369224b036a1fb77849f7ae65b3492c832c0buzbee DCHECK_EQ(cUnit->instructionSet, kThumb2); 375efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Unused - RegLocation rlSrcUnsafe = info->args[0]; 376efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrcObj= info->args[1]; // Object - known non-null 377efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrcOffset= info->args[2]; // long low 378efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrcOffset.wide = 0; // ignore high half in info->args[3] 379efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrcExpected= info->args[4]; // int or Object 380efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrcNewValue= info->args[5]; // int or Object 381efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlDest = inlineTarget(cUnit, info); // boolean place for result 382efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 383efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 3841bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee // Release store semantics, get the barrier out of the way. TODO: revisit 3851bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee oatGenMemBarrier(cUnit, kStoreLoad); 386efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 387efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlObject = loadValue(cUnit, rlSrcObj, kCoreReg); 388efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlNewValue = loadValue(cUnit, rlSrcNewValue, kCoreReg); 389efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 390efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (need_write_barrier) { 391efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Mark card for object assuming new value is stored. 392efc6369224b036a1fb77849f7ae65b3492c832c0buzbee markGCCard(cUnit, rlNewValue.lowReg, rlObject.lowReg); 393efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 394efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 395efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlOffset = loadValue(cUnit, rlSrcOffset, kCoreReg); 396efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 397efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int rPtr = oatAllocTemp(cUnit); 398efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegReg(cUnit, kOpAdd, rPtr, rlObject.lowReg, rlOffset.lowReg); 399efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 400efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Free now unneeded rlObject and rlOffset to give more temps. 401efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatClobberSReg(cUnit, rlObject.sRegLow); 402efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, rlObject.lowReg); 403efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatClobberSReg(cUnit, rlOffset.sRegLow); 404efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, rlOffset.lowReg); 405efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 406efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int rOldValue = oatAllocTemp(cUnit); 407efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR3(cUnit, kThumb2Ldrex, rOldValue, rPtr, 0); // rOldValue := [rPtr] 408efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 409efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlExpected = loadValue(cUnit, rlSrcExpected, kCoreReg); 410efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 411efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // if (rOldValue == rExpected) { 412efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // [rPtr] <- rNewValue && rResult := success ? 0 : 1 413efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // rResult ^= 1 414efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // } else { 415efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // rResult := 0 416efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // } 417efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpCmp, rOldValue, rlExpected.lowReg); 418efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, rOldValue); // Now unneeded. 419efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); 420efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opIT(cUnit, kArmCondEq, "TE"); 421efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR4(cUnit, kThumb2Strex, rlResult.lowReg, rlNewValue.lowReg, rPtr, 0); 422efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, rPtr); // Now unneeded. 423efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegImm(cUnit, kOpXor, rlResult.lowReg, 1); 424efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegReg(cUnit, kOpXor, rlResult.lowReg, rlResult.lowReg); 425efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 426efc6369224b036a1fb77849f7ae65b3492c832c0buzbee storeValue(cUnit, rlDest, rlResult); 427efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 428efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return true; 429efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 430efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 431efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opPcRelLoad(CompilationUnit* cUnit, int reg, LIR* target) 432efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 433efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2LdrPcRel12, reg, 0, 0, 0, 0, target); 434efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 435efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 436efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opVldm(CompilationUnit* cUnit, int rBase, int count) 437efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 438efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return newLIR3(cUnit, kThumb2Vldms, rBase, fr0, count); 439efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 440efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 441efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opVstm(CompilationUnit* cUnit, int rBase, int count) 442efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 443efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return newLIR3(cUnit, kThumb2Vstms, rBase, fr0, count); 444efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 445efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 446efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genMultiplyByTwoBitMultiplier(CompilationUnit* cUnit, RegLocation rlSrc, 447efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlResult, int lit, 448efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int firstBit, int secondBit) 449efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 450efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg, 451efc6369224b036a1fb77849f7ae65b3492c832c0buzbee encodeShift(kArmLsl, secondBit - firstBit)); 452efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (firstBit != 0) { 453efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit); 454efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 455efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 456efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 457efc6369224b036a1fb77849f7ae65b3492c832c0buzbeevoid genDivZeroCheck(CompilationUnit* cUnit, int regLo, int regHi) 458efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 459efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int tReg = oatAllocTemp(cUnit); 460efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR4(cUnit, kThumb2OrrRRRs, tReg, regLo, regHi, 0); 461efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, tReg); 462efc6369224b036a1fb77849f7ae65b3492c832c0buzbee genCheck(cUnit, kCondEq, kThrowDivZero); 463efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 464efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 465efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Test suspend flag, return target of taken suspend branch 466efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opTestSuspend(CompilationUnit* cUnit, LIR* target) 467efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 468efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR2(cUnit, kThumbSubRI8, rARM_SUSPEND, 1); 469efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return opCondBranch(cUnit, (target == NULL) ? kCondEq : kCondNe, target); 470efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 471efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 472efc6369224b036a1fb77849f7ae65b3492c832c0buzbee// Decrement register and branch on condition 473efc6369224b036a1fb77849f7ae65b3492c832c0buzbeeLIR* opDecAndBranch(CompilationUnit* cUnit, ConditionCode cCode, int reg, LIR* target) 474efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 475efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Combine sub & test using sub setflags encoding here 476efc6369224b036a1fb77849f7ae65b3492c832c0buzbee newLIR3(cUnit, kThumb2SubsRRI12, reg, reg, 1); 477efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return opCondBranch(cUnit, cCode, target); 478efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 479efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 4801bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbeevoid oatGenMemBarrier(CompilationUnit* cUnit, MemBarrierKind barrierKind) 481efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 482efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#if ANDROID_SMP != 0 4831bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee int dmbFlavor; 4841bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee // TODO: revisit Arm barrier kinds 4851bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee switch (barrierKind) { 4861bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee case kLoadStore: dmbFlavor = kSY; break; 4871bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee case kLoadLoad: dmbFlavor = kSY; break; 4881bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee case kStoreStore: dmbFlavor = kST; break; 4891bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee case kStoreLoad: dmbFlavor = kSY; break; 4901bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee default: 4911bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee LOG(FATAL) << "Unexpected MemBarrierKind: " << barrierKind; 4921bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee dmbFlavor = kSY; // quiet gcc. 4931bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee break; 4941bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee } 4951bc37c60da71c923ea9a2e99d31ba1b3d76d79a8buzbee LIR* dmb = newLIR1(cUnit, kThumb2Dmb, dmbFlavor); 496efc6369224b036a1fb77849f7ae65b3492c832c0buzbee dmb->defMask = ENCODE_ALL; 497efc6369224b036a1fb77849f7ae65b3492c832c0buzbee#endif 498efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 499efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 500efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genNegLong(CompilationUnit* cUnit, RegLocation rlDest, 501efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc) 502efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 503efc6369224b036a1fb77849f7ae65b3492c832c0buzbee rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); 504efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); 505efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int zReg = oatAllocTemp(cUnit); 506efc6369224b036a1fb77849f7ae65b3492c832c0buzbee loadConstantNoClobber(cUnit, zReg, 0); 507efc6369224b036a1fb77849f7ae65b3492c832c0buzbee // Check for destructive overlap 508efc6369224b036a1fb77849f7ae65b3492c832c0buzbee if (rlResult.lowReg == rlSrc.highReg) { 509efc6369224b036a1fb77849f7ae65b3492c832c0buzbee int tReg = oatAllocTemp(cUnit); 510efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg); 511efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, tReg); 512efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, tReg); 513efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } else { 514efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegReg(cUnit, kOpSub, rlResult.lowReg, zReg, rlSrc.lowReg); 515efc6369224b036a1fb77849f7ae65b3492c832c0buzbee opRegRegReg(cUnit, kOpSbc, rlResult.highReg, zReg, rlSrc.highReg); 516efc6369224b036a1fb77849f7ae65b3492c832c0buzbee } 517efc6369224b036a1fb77849f7ae65b3492c832c0buzbee oatFreeTemp(cUnit, zReg); 518efc6369224b036a1fb77849f7ae65b3492c832c0buzbee storeValueWide(cUnit, rlDest, rlResult); 519efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 520efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 521efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 522efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genAddLong(CompilationUnit* cUnit, RegLocation rlDest, 523efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1, RegLocation rlSrc2) 524efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 525efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genAddLong for Arm"; 526efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 527efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 528efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 529efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genSubLong(CompilationUnit* cUnit, RegLocation rlDest, 530efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1, RegLocation rlSrc2) 531efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 532efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genSubLong for Arm"; 533efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 534efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 535efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 536efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genAndLong(CompilationUnit* cUnit, RegLocation rlDest, 537efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1, RegLocation rlSrc2) 538efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 539efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genAndLong for Arm"; 540efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 541efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 542efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 543efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genOrLong(CompilationUnit* cUnit, RegLocation rlDest, 544efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1, RegLocation rlSrc2) 545efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 546efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genOrLong for Arm"; 547efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 548efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 549efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 550efc6369224b036a1fb77849f7ae65b3492c832c0buzbeebool genXorLong(CompilationUnit* cUnit, RegLocation rlDest, 551efc6369224b036a1fb77849f7ae65b3492c832c0buzbee RegLocation rlSrc1, RegLocation rlSrc2) 552efc6369224b036a1fb77849f7ae65b3492c832c0buzbee{ 553efc6369224b036a1fb77849f7ae65b3492c832c0buzbee LOG(FATAL) << "Unexpected use of genXoLong for Arm"; 554efc6369224b036a1fb77849f7ae65b3492c832c0buzbee return false; 555efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} 556efc6369224b036a1fb77849f7ae65b3492c832c0buzbee 557efc6369224b036a1fb77849f7ae65b3492c832c0buzbee} // namespace art 558