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