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.DalvInsn;
     20 import com.android.dx.dex.code.InsnFormat;
     21 import com.android.dx.dex.code.SimpleInsn;
     22 import com.android.dx.rop.code.RegisterSpec;
     23 import com.android.dx.rop.code.RegisterSpecList;
     24 import com.android.dx.util.AnnotatedOutput;
     25 import java.util.BitSet;
     26 
     27 /**
     28  * Instruction format {@code 12x}. See the instruction format spec
     29  * for details.
     30  */
     31 public final class Form12x extends InsnFormat {
     32     /** {@code non-null;} unique instance of this class */
     33     public static final InsnFormat THE_ONE = new Form12x();
     34 
     35     /**
     36      * Constructs an instance. This class is not publicly
     37      * instantiable. Use {@link #THE_ONE}.
     38      */
     39     private Form12x() {
     40         // This space intentionally left blank.
     41     }
     42 
     43     /** {@inheritDoc} */
     44     @Override
     45     public String insnArgString(DalvInsn insn) {
     46         RegisterSpecList regs = insn.getRegisters();
     47         int sz = regs.size();
     48 
     49         /*
     50          * The (sz - 2) and (sz - 1) below makes this code work for
     51          * both the two- and three-register ops. (See "case 3" in
     52          * isCompatible(), below.)
     53          */
     54 
     55         return regs.get(sz - 2).regString() + ", " +
     56             regs.get(sz - 1).regString();
     57     }
     58 
     59     /** {@inheritDoc} */
     60     @Override
     61     public String insnCommentString(DalvInsn insn, boolean noteIndices) {
     62         // This format has no comment.
     63         return "";
     64     }
     65 
     66     /** {@inheritDoc} */
     67     @Override
     68     public int codeSize() {
     69         return 1;
     70     }
     71 
     72     /** {@inheritDoc} */
     73     @Override
     74     public boolean isCompatible(DalvInsn insn) {
     75         if (!(insn instanceof SimpleInsn)) {
     76             return false;
     77         }
     78 
     79         RegisterSpecList regs = insn.getRegisters();
     80         RegisterSpec rs1;
     81         RegisterSpec rs2;
     82 
     83         switch (regs.size()) {
     84             case 2: {
     85                 rs1 = regs.get(0);
     86                 rs2 = regs.get(1);
     87                 break;
     88             }
     89             case 3: {
     90                 /*
     91                  * This format is allowed for ops that are effectively
     92                  * 3-arg but where the first two args are identical.
     93                  */
     94                 rs1 = regs.get(1);
     95                 rs2 = regs.get(2);
     96                 if (rs1.getReg() != regs.get(0).getReg()) {
     97                     return false;
     98                 }
     99                 break;
    100             }
    101             default: {
    102                 return false;
    103             }
    104         }
    105 
    106         return unsignedFitsInNibble(rs1.getReg()) &&
    107             unsignedFitsInNibble(rs2.getReg());
    108     }
    109 
    110     /** {@inheritDoc} */
    111     @Override
    112     public BitSet compatibleRegs(DalvInsn insn) {
    113         RegisterSpecList regs = insn.getRegisters();
    114         BitSet bits = new BitSet(2);
    115         int r0 = regs.get(0).getReg();
    116         int r1 = regs.get(1).getReg();
    117 
    118         switch (regs.size()) {
    119           case 2: {
    120             bits.set(0, unsignedFitsInNibble(r0));
    121             bits.set(1, unsignedFitsInNibble(r1));
    122             break;
    123           }
    124           case 3: {
    125             if (r0 != r1) {
    126                 bits.set(0, false);
    127                 bits.set(1, false);
    128             } else {
    129                 boolean dstRegComp = unsignedFitsInNibble(r1);
    130                 bits.set(0, dstRegComp);
    131                 bits.set(1, dstRegComp);
    132             }
    133 
    134             bits.set(2, unsignedFitsInNibble(regs.get(2).getReg()));
    135             break;
    136           }
    137           default: {
    138             throw new AssertionError();
    139           }
    140         }
    141 
    142         return bits;
    143     }
    144 
    145     /** {@inheritDoc} */
    146     @Override
    147     public void writeTo(AnnotatedOutput out, DalvInsn insn) {
    148         RegisterSpecList regs = insn.getRegisters();
    149         int sz = regs.size();
    150 
    151         /*
    152          * The (sz - 2) and (sz - 1) below makes this code work for
    153          * both the two- and three-register ops. (See "case 3" in
    154          * isCompatible(), above.)
    155          */
    156 
    157         write(out, opcodeUnit(insn,
    158                               makeByte(regs.get(sz - 2).getReg(),
    159                                        regs.get(sz - 1).getReg())));
    160     }
    161 }
    162