Home | History | Annotate | Download | only in code
      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