1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/* 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License. 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License. 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.dex.code; 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.io.OpcodeInfo; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.io.Opcodes; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Representation of an opcode. 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class Dop { 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code Opcodes.isValid();} the opcode value itself */ 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int opcode; 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code Opcodes.isValid();} the opcode family */ 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int family; 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code Opcodes.isValid();} what opcode (by number) to try next 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * when attempting to match an opcode to particular arguments; 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code Opcodes.NO_NEXT} to indicate that this is the last 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * opcode to try in a particular chain 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int nextOpcode; 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code non-null;} the instruction format */ 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final InsnFormat format; 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** whether this opcode uses a result register */ 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final boolean hasResult; 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs an instance. 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param opcode {@code Opcodes.isValid();} the opcode value 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * itself 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param family {@code Opcodes.isValid();} the opcode family 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param nextOpcode {@code Opcodes.isValid();} what opcode (by 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * number) to try next when attempting to match an opcode to 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * particular arguments; {@code Opcodes.NO_NEXT} to indicate that 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * this is the last opcode to try in a particular chain 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param format {@code non-null;} the instruction format 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param hasResult whether the opcode has a result register; if so it 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is always the first register 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Dop(int opcode, int family, int nextOpcode, InsnFormat format, 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson boolean hasResult) { 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!Opcodes.isValidShape(opcode)) { 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("bogus opcode"); 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!Opcodes.isValidShape(family)) { 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("bogus family"); 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!Opcodes.isValidShape(nextOpcode)) { 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("bogus nextOpcode"); 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (format == null) { 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new NullPointerException("format == null"); 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.opcode = opcode; 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.family = family; 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.nextOpcode = nextOpcode; 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.format = format; 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.hasResult = hasResult; 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toString() { 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return getName(); 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the opcode value. 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode value 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getOpcode() { 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return opcode; 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the opcode family. The opcode family is the unmarked (no 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * "/...") opcode that has equivalent semantics to this one. 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode family 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getFamily() { 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return family; 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the instruction format. 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the instruction format 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public InsnFormat getFormat() { 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return format; 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns whether this opcode uses a result register. 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code true} iff this opcode uses a result register 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean hasResult() { 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return hasResult; 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the opcode name. 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the opcode name 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String getName() { 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return OpcodeInfo.getName(opcode); 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the opcode value to try next when attempting to match an 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * opcode to particular arguments. This returns {@code 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Opcodes.NO_NEXT} to indicate that this is the last opcode to 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * try in a particular chain. 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code Opcodes.MIN_VALUE..Opcodes.MAX_VALUE;} the opcode value 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getNextOpcode() { 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return nextOpcode; 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the opcode for the opposite test of this instance. This is only 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * valid for opcodes which are in fact tests. 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} the opposite test 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Dop getOppositeTest() { 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson switch (opcode) { 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_EQ: return Dops.IF_NE; 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_NE: return Dops.IF_EQ; 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_LT: return Dops.IF_GE; 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_GE: return Dops.IF_LT; 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_GT: return Dops.IF_LE; 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_LE: return Dops.IF_GT; 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_EQZ: return Dops.IF_NEZ; 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_NEZ: return Dops.IF_EQZ; 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_LTZ: return Dops.IF_GEZ; 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_GEZ: return Dops.IF_LTZ; 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_GTZ: return Dops.IF_LEZ; 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson case Opcodes.IF_LEZ: return Dops.IF_GTZ; 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException("bogus opcode: " + this); 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 174