1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.dx.rop.code; 18 19import com.android.dx.rop.cst.CstInteger; 20import com.android.dx.rop.type.Type; 21 22/** 23 * Implementation of {@link TranslationAdvice} which represents what 24 * the dex format will be able to represent. 25 */ 26public final class DexTranslationAdvice 27 implements TranslationAdvice { 28 /** {@code non-null;} standard instance of this class */ 29 public static final DexTranslationAdvice THE_ONE = 30 new DexTranslationAdvice(); 31 32 /** debug advice for disabling invoke-range optimization */ 33 public static final DexTranslationAdvice NO_SOURCES_IN_ORDER = 34 new DexTranslationAdvice(true); 35 36 /** 37 * The minimum source width, in register units, for an invoke 38 * instruction that requires its sources to be in order and contiguous. 39 */ 40 private static final int MIN_INVOKE_IN_ORDER = 6; 41 42 /** when true: always returns false for requiresSourcesInOrder */ 43 private final boolean disableSourcesInOrder; 44 45 /** 46 * This class is not publicly instantiable. Use {@link #THE_ONE}. 47 */ 48 private DexTranslationAdvice() { 49 disableSourcesInOrder = false; 50 } 51 52 private DexTranslationAdvice(boolean disableInvokeRange) { 53 this.disableSourcesInOrder = disableInvokeRange; 54 } 55 56 /** {@inheritDoc} */ 57 public boolean hasConstantOperation(Rop opcode, 58 RegisterSpec sourceA, RegisterSpec sourceB) { 59 if (sourceA.getType() != Type.INT) { 60 return false; 61 } 62 63 if (! (sourceB.getTypeBearer() instanceof CstInteger)) { 64 return false; 65 } 66 67 CstInteger cst = (CstInteger) sourceB.getTypeBearer(); 68 69 // TODO handle rsub 70 switch (opcode.getOpcode()) { 71 // These have 8 and 16 bit cst representations 72 case RegOps.REM: 73 case RegOps.ADD: 74 case RegOps.MUL: 75 case RegOps.DIV: 76 case RegOps.AND: 77 case RegOps.OR: 78 case RegOps.XOR: 79 return cst.fitsIn16Bits(); 80 // These only have 8 bit cst reps 81 case RegOps.SHL: 82 case RegOps.SHR: 83 case RegOps.USHR: 84 return cst.fitsIn8Bits(); 85 default: 86 return false; 87 } 88 } 89 90 /** {@inheritDoc} */ 91 public boolean requiresSourcesInOrder(Rop opcode, 92 RegisterSpecList sources) { 93 94 return !disableSourcesInOrder && opcode.isCallLike() 95 && totalRopWidth(sources) >= MIN_INVOKE_IN_ORDER; 96 } 97 98 /** 99 * Calculates the total rop width of the list of SSA registers 100 * 101 * @param sources {@code non-null;} list of SSA registers 102 * @return {@code >= 0;} rop-form width in register units 103 */ 104 private int totalRopWidth(RegisterSpecList sources) { 105 int sz = sources.size(); 106 int total = 0; 107 108 for (int i = 0; i < sz; i++) { 109 total += sources.get(i).getCategory(); 110 } 111 112 return total; 113 } 114 115 /** {@inheritDoc} */ 116 public int getMaxOptimalRegisterCount() { 117 return 16; 118 } 119} 120