/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.dexgen.dex.code; /** * Representation of an opcode. */ public final class Dop { /** DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode value itself */ private final int opcode; /** DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode family */ private final int family; /** {@code non-null;} the instruction format */ private final InsnFormat format; /** whether this opcode uses a result register */ private final boolean hasResult; /** {@code non-null;} the name */ private final String name; /** * Constructs an instance. * * @param opcode {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode * value itself * @param family {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family * @param format {@code non-null;} the instruction format * @param hasResult whether the opcode has a result register; if so it * is always the first register * @param name {@code non-null;} the name */ public Dop(int opcode, int family, InsnFormat format, boolean hasResult, String name) { if ((opcode < DalvOps.MIN_VALUE) || (opcode > DalvOps.MAX_VALUE)) { throw new IllegalArgumentException("bogus opcode"); } if ((family < DalvOps.MIN_VALUE) || (family > DalvOps.MAX_VALUE)) { throw new IllegalArgumentException("bogus family"); } if (format == null) { throw new NullPointerException("format == null"); } if (name == null) { throw new NullPointerException("name == null"); } this.opcode = opcode; this.family = family; this.format = format; this.hasResult = hasResult; this.name = name; } /** {@inheritDoc} */ @Override public String toString() { return name; } /** * Gets the opcode value. * * @return {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode value */ public int getOpcode() { return opcode; } /** * Gets the opcode family. The opcode family is the unmarked (no * "/...") opcode that has equivalent semantics to this one. * * @return {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family */ public int getFamily() { return family; } /** * Gets the instruction format. * * @return {@code non-null;} the instruction format */ public InsnFormat getFormat() { return format; } /** * Returns whether this opcode uses a result register. * * @return {@code true} iff this opcode uses a result register */ public boolean hasResult() { return hasResult; } /** * Gets the opcode name. * * @return {@code non-null;} the opcode name */ public String getName() { return name; } /** * Gets the opcode for the opposite test of this instance. This is only * valid for opcodes which are in fact tests. * * @return {@code non-null;} the opposite test */ public Dop getOppositeTest() { switch (opcode) { case DalvOps.IF_EQ: return Dops.IF_NE; case DalvOps.IF_NE: return Dops.IF_EQ; case DalvOps.IF_LT: return Dops.IF_GE; case DalvOps.IF_GE: return Dops.IF_LT; case DalvOps.IF_GT: return Dops.IF_LE; case DalvOps.IF_LE: return Dops.IF_GT; case DalvOps.IF_EQZ: return Dops.IF_NEZ; case DalvOps.IF_NEZ: return Dops.IF_EQZ; case DalvOps.IF_LTZ: return Dops.IF_GEZ; case DalvOps.IF_GEZ: return Dops.IF_LTZ; case DalvOps.IF_GTZ: return Dops.IF_LEZ; case DalvOps.IF_LEZ: return Dops.IF_GTZ; } throw new IllegalArgumentException("bogus opcode: " + this); } }