Home | History | Annotate | Download | only in form
      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.dex.code.form;
     18 
     19 import com.android.dx.dex.code.CstInsn;
     20 import com.android.dx.dex.code.DalvInsn;
     21 import com.android.dx.dex.code.InsnFormat;
     22 import com.android.dx.rop.code.RegisterSpec;
     23 import com.android.dx.rop.code.RegisterSpecList;
     24 import com.android.dx.rop.cst.Constant;
     25 import com.android.dx.rop.cst.CstFieldRef;
     26 import com.android.dx.rop.cst.CstMethodHandle;
     27 import com.android.dx.rop.cst.CstProtoRef;
     28 import com.android.dx.rop.cst.CstString;
     29 import com.android.dx.rop.cst.CstType;
     30 import com.android.dx.util.AnnotatedOutput;
     31 import java.util.BitSet;
     32 
     33 /**
     34  * Instruction format {@code 21c}. See the instruction format spec
     35  * for details.
     36  */
     37 public final class Form21c extends InsnFormat {
     38     /** {@code non-null;} unique instance of this class */
     39     public static final InsnFormat THE_ONE = new Form21c();
     40 
     41     /**
     42      * Constructs an instance. This class is not publicly
     43      * instantiable. Use {@link #THE_ONE}.
     44      */
     45     private Form21c() {
     46         // This space intentionally left blank.
     47     }
     48 
     49     /** {@inheritDoc} */
     50     @Override
     51     public String insnArgString(DalvInsn insn) {
     52         RegisterSpecList regs = insn.getRegisters();
     53         return regs.get(0).regString() + ", " + insn.cstString();
     54     }
     55 
     56     /** {@inheritDoc} */
     57     @Override
     58     public String insnCommentString(DalvInsn insn, boolean noteIndices) {
     59         if (noteIndices) {
     60             return insn.cstComment();
     61         } else {
     62             return "";
     63         }
     64     }
     65 
     66     /** {@inheritDoc} */
     67     @Override
     68     public int codeSize() {
     69         return 2;
     70     }
     71 
     72     /** {@inheritDoc} */
     73     @Override
     74     public boolean isCompatible(DalvInsn insn) {
     75         if (!(insn instanceof CstInsn)) {
     76             return false;
     77         }
     78 
     79         RegisterSpecList regs = insn.getRegisters();
     80         RegisterSpec reg;
     81 
     82         switch (regs.size()) {
     83             case 1: {
     84                 reg = regs.get(0);
     85                 break;
     86             }
     87             case 2: {
     88                 /*
     89                  * This format is allowed for ops that are effectively
     90                  * 2-arg but where the two args are identical.
     91                  */
     92                 reg = regs.get(0);
     93                 if (reg.getReg() != regs.get(1).getReg()) {
     94                     return false;
     95                 }
     96                 break;
     97             }
     98             default: {
     99                 return false;
    100             }
    101         }
    102 
    103         if (!unsignedFitsInByte(reg.getReg())) {
    104             return false;
    105         }
    106 
    107         CstInsn ci = (CstInsn) insn;
    108         int cpi = ci.getIndex();
    109         Constant cst = ci.getConstant();
    110 
    111         if (! unsignedFitsInShort(cpi)) {
    112             return false;
    113         }
    114 
    115         return cst instanceof CstType ||
    116             cst instanceof CstFieldRef ||
    117             cst instanceof CstString ||
    118             cst instanceof CstMethodHandle ||
    119             cst instanceof CstProtoRef;
    120     }
    121 
    122     /** {@inheritDoc} */
    123     @Override
    124     public BitSet compatibleRegs(DalvInsn insn) {
    125         RegisterSpecList regs = insn.getRegisters();
    126         int sz = regs.size();
    127         BitSet bits = new BitSet(sz);
    128         boolean compat = unsignedFitsInByte(regs.get(0).getReg());
    129 
    130         if (sz == 1) {
    131             bits.set(0, compat);
    132         } else {
    133             if (regs.get(0).getReg() == regs.get(1).getReg()) {
    134                 bits.set(0, compat);
    135                 bits.set(1, compat);
    136             }
    137         }
    138 
    139         return bits;
    140     }
    141 
    142     /** {@inheritDoc} */
    143     @Override
    144     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
    145         RegisterSpecList regs = insn.getRegisters();
    146         int cpi = ((CstInsn) insn).getIndex();
    147 
    148         write(out,
    149               opcodeUnit(insn, regs.get(0).getReg()),
    150               (short) cpi);
    151     }
    152 }
    153