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.dex.code;
     18 
     19 import com.android.dx.io.OpcodeInfo;
     20 import com.android.dx.io.Opcodes;
     21 
     22 /**
     23  * Representation of an opcode.
     24  */
     25 public final class Dop {
     26     /** {@code Opcodes.isValid();} the opcode value itself */
     27     private final int opcode;
     28 
     29     /** {@code Opcodes.isValid();} the opcode family */
     30     private final int family;
     31 
     32     /**
     33      * {@code Opcodes.isValid();} what opcode (by number) to try next
     34      * when attempting to match an opcode to particular arguments;
     35      * {@code Opcodes.NO_NEXT} to indicate that this is the last
     36      * opcode to try in a particular chain
     37      */
     38     private final int nextOpcode;
     39 
     40     /** {@code non-null;} the instruction format */
     41     private final InsnFormat format;
     42 
     43     /** whether this opcode uses a result register */
     44     private final boolean hasResult;
     45 
     46     /**
     47      * Constructs an instance.
     48      *
     49      * @param opcode {@code Opcodes.isValid();} the opcode value
     50      * itself
     51      * @param family {@code Opcodes.isValid();} the opcode family
     52      * @param nextOpcode {@code Opcodes.isValid();} what opcode (by
     53      * number) to try next when attempting to match an opcode to
     54      * particular arguments; {@code Opcodes.NO_NEXT} to indicate that
     55      * this is the last opcode to try in a particular chain
     56      * @param format {@code non-null;} the instruction format
     57      * @param hasResult whether the opcode has a result register; if so it
     58      * is always the first register
     59      */
     60     public Dop(int opcode, int family, int nextOpcode, InsnFormat format,
     61             boolean hasResult) {
     62         if (!Opcodes.isValidShape(opcode)) {
     63             throw new IllegalArgumentException("bogus opcode");
     64         }
     65 
     66         if (!Opcodes.isValidShape(family)) {
     67             throw new IllegalArgumentException("bogus family");
     68         }
     69 
     70         if (!Opcodes.isValidShape(nextOpcode)) {
     71             throw new IllegalArgumentException("bogus nextOpcode");
     72         }
     73 
     74         if (format == null) {
     75             throw new NullPointerException("format == null");
     76         }
     77 
     78         this.opcode = opcode;
     79         this.family = family;
     80         this.nextOpcode = nextOpcode;
     81         this.format = format;
     82         this.hasResult = hasResult;
     83     }
     84 
     85     /** {@inheritDoc} */
     86     @Override
     87     public String toString() {
     88         return getName();
     89     }
     90 
     91     /**
     92      * Gets the opcode value.
     93      *
     94      * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode value
     95      */
     96     public int getOpcode() {
     97         return opcode;
     98     }
     99 
    100     /**
    101      * Gets the opcode family. The opcode family is the unmarked (no
    102      * "/...") opcode that has equivalent semantics to this one.
    103      *
    104      * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode family
    105      */
    106     public int getFamily() {
    107         return family;
    108     }
    109 
    110     /**
    111      * Gets the instruction format.
    112      *
    113      * @return {@code non-null;} the instruction format
    114      */
    115     public InsnFormat getFormat() {
    116         return format;
    117     }
    118 
    119     /**
    120      * Returns whether this opcode uses a result register.
    121      *
    122      * @return {@code true} iff this opcode uses a result register
    123      */
    124     public boolean hasResult() {
    125         return hasResult;
    126     }
    127 
    128     /**
    129      * Gets the opcode name.
    130      *
    131      * @return {@code non-null;} the opcode name
    132      */
    133     public String getName() {
    134         return OpcodeInfo.getName(opcode);
    135     }
    136 
    137     /**
    138      * Gets the opcode value to try next when attempting to match an
    139      * opcode to particular arguments. This returns {@code
    140      * Opcodes.NO_NEXT} to indicate that this is the last opcode to
    141      * try in a particular chain.
    142      *
    143      * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode value
    144      */
    145     public int getNextOpcode() {
    146         return nextOpcode;
    147     }
    148 
    149     /**
    150      * Gets the opcode for the opposite test of this instance. This is only
    151      * valid for opcodes which are in fact tests.
    152      *
    153      * @return {@code non-null;} the opposite test
    154      */
    155     public Dop getOppositeTest() {
    156         switch (opcode) {
    157             case Opcodes.IF_EQ:  return Dops.IF_NE;
    158             case Opcodes.IF_NE:  return Dops.IF_EQ;
    159             case Opcodes.IF_LT:  return Dops.IF_GE;
    160             case Opcodes.IF_GE:  return Dops.IF_LT;
    161             case Opcodes.IF_GT:  return Dops.IF_LE;
    162             case Opcodes.IF_LE:  return Dops.IF_GT;
    163             case Opcodes.IF_EQZ: return Dops.IF_NEZ;
    164             case Opcodes.IF_NEZ: return Dops.IF_EQZ;
    165             case Opcodes.IF_LTZ: return Dops.IF_GEZ;
    166             case Opcodes.IF_GEZ: return Dops.IF_LTZ;
    167             case Opcodes.IF_GTZ: return Dops.IF_LEZ;
    168             case Opcodes.IF_LEZ: return Dops.IF_GTZ;
    169         }
    170 
    171         throw new IllegalArgumentException("bogus opcode: " + this);
    172     }
    173 }
    174