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 17 package com.android.dx.rop.code; 18 19 import com.android.dx.rop.cst.CstInteger; 20 import 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 */ 26 public 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 // Return false if second source isn't a constant 64 if (! (sourceB.getTypeBearer() instanceof CstInteger)) { 65 // Except for rsub-int (reverse sub) where first source is constant 66 if (sourceA.getTypeBearer() instanceof CstInteger && 67 opcode.getOpcode() == RegOps.SUB) { 68 CstInteger cst = (CstInteger) sourceA.getTypeBearer(); 69 return cst.fitsIn16Bits(); 70 } else { 71 return false; 72 } 73 } 74 75 CstInteger cst = (CstInteger) sourceB.getTypeBearer(); 76 77 switch (opcode.getOpcode()) { 78 // These have 8 and 16 bit cst representations 79 case RegOps.REM: 80 case RegOps.ADD: 81 case RegOps.MUL: 82 case RegOps.DIV: 83 case RegOps.AND: 84 case RegOps.OR: 85 case RegOps.XOR: 86 return cst.fitsIn16Bits(); 87 // These only have 8 bit cst reps 88 case RegOps.SHL: 89 case RegOps.SHR: 90 case RegOps.USHR: 91 return cst.fitsIn8Bits(); 92 // No sub-const insn, so check if equivalent add-const fits 93 case RegOps.SUB: 94 CstInteger cst2 = CstInteger.make(-cst.getValue()); 95 return cst2.fitsIn16Bits(); 96 default: 97 return false; 98 } 99 } 100 101 /** {@inheritDoc} */ 102 public boolean requiresSourcesInOrder(Rop opcode, 103 RegisterSpecList sources) { 104 105 return !disableSourcesInOrder && opcode.isCallLike() 106 && totalRopWidth(sources) >= MIN_INVOKE_IN_ORDER; 107 } 108 109 /** 110 * Calculates the total rop width of the list of SSA registers 111 * 112 * @param sources {@code non-null;} list of SSA registers 113 * @return {@code >= 0;} rop-form width in register units 114 */ 115 private int totalRopWidth(RegisterSpecList sources) { 116 int sz = sources.size(); 117 int total = 0; 118 119 for (int i = 0; i < sz; i++) { 120 total += sources.get(i).getCategory(); 121 } 122 123 return total; 124 } 125 126 /** {@inheritDoc} */ 127 public int getMaxOptimalRegisterCount() { 128 return 16; 129 } 130 } 131