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     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