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 17package com.android.dexgen.dex.code; 18 19/** 20 * Representation of an opcode. 21 */ 22public 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