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