001 package sysModel.classFile.code.instructions;
002
003 import sysModel.classFile.code.Opcode;
004
005 import java.util.Arrays;
006
007 /**
008 * Generic Java instruction.
009 *
010 * @author Mathias Ricken
011 */
012 public class GenericInstruction extends AInstruction {
013 /**
014 * Bytecode.
015 */
016 protected byte[] _code;
017
018 /**
019 * Constructor.
020 *
021 * @param code bytecode for generic instruction
022 */
023 public GenericInstruction(byte[] code) {
024 switch(code[0]) {
025 case Opcode.TABLESWITCH:
026 case Opcode.LOOKUPSWITCH:
027 case Opcode.IFEQ:
028 case Opcode.IFNE:
029 case Opcode.IFLT:
030 case Opcode.IFGE:
031 case Opcode.IFGT:
032 case Opcode.IFLE:
033 case Opcode.IF_ICMPEQ:
034 case Opcode.IF_ICMPNE:
035 case Opcode.IF_ICMPLT:
036 case Opcode.IF_ICMPGE:
037 case Opcode.IF_ICMPGT:
038 case Opcode.IF_ICMPLE:
039 case Opcode.IF_ACMPEQ:
040 case Opcode.IF_ACMPNE:
041 case Opcode.GOTO:
042 case Opcode.JSR:
043 case Opcode.IFNULL:
044 case Opcode.IFNONNULL:
045 case Opcode.GOTO_W:
046 case Opcode.JSR_W:
047 case Opcode.WIDE:
048 throw new IllegalArgumentException("Invalid generic opcode");
049 }
050 _code = code;
051 }
052
053 /**
054 * Get the opcode of this instruction.
055 *
056 * @return opcode
057 */
058 public byte getOpcode() {
059 return _code[0];
060 }
061
062 /**
063 * Get the length bytecode for this instruction, padded for the specified program counter value.
064 *
065 * @param pc PC for padding
066 *
067 * @return bytecode length
068 */
069 public short getBytecodeLength(short pc) {
070 return (short)Opcode.getInstrSize(_code, 0, 0);
071 }
072
073 /**
074 * Make a new generic instruction from the bytecode stating at pc, padded using paddingPC, and use the line number
075 * table for branches.
076 *
077 * @param bytecode bytecode
078 * @param pc starting index in bytecode
079 * @param paddingPC PC for padding
080 * @param lnt line number table for branches
081 */
082 public GenericInstruction(byte[] bytecode, short pc, short paddingPC, LineNumberTable lnt) {
083 _code = new byte[Opcode.getInstrSize(bytecode, pc, paddingPC)];
084 System.arraycopy(bytecode, pc, _code, 0, _code.length);
085 }
086
087 /**
088 * Get the bytecode for this instruction, padded for the specified program counter value, with branch targets
089 * according to the specified line number table
090 *
091 * @param pc PC for padding
092 * @param lnt line number table for branches
093 *
094 * @return bytecode
095 */
096 public byte[] getBytecode(short pc, LineNumberTable lnt) {
097 return getBytecode();
098 }
099
100 /**
101 * Get the bytecode for this instruction.
102 *
103 * @return bytecode
104 */
105 public byte[] getBytecode() {
106 byte[] b = new byte[_code.length];
107 System.arraycopy(_code, 0, b, 0, _code.length);
108 return b;
109 }
110
111 /**
112 * Return true of this instruction and the other object are equal.
113 *
114 * @param o other object
115 *
116 * @return true if equal
117 */
118 public boolean equals(Object o) {
119 if (this == o) {
120 return true;
121 }
122 if (!(o instanceof GenericInstruction)) {
123 return false;
124 }
125
126 GenericInstruction genericInstruction = (GenericInstruction)o;
127 return Arrays.equals(_code, genericInstruction._code);
128
129 }
130
131 /**
132 * Return hash code.
133 *
134 * @return hash code
135 */
136 public int hashCode() {
137 return _code[0];
138 }
139
140 /**
141 * Return an array of target indices.
142 *
143 * @return array of target indices.
144 */
145 public short[] getBranchTargets() {
146 return new short[0];
147 }
148
149 /**
150 * Set the branch target indices.
151 *
152 * @param branchTargets array of target indices
153 */
154 public void setBranchTargets(short[] branchTargets) {
155 if (0 != branchTargets.length) {
156 throw new IllegalArgumentException("Generic instruction cannot have a target");
157 }
158 }
159
160 /**
161 * Return instruction in human-readable form.
162 *
163 * @return string representation
164 */
165 public String toString() {
166 StringBuffer x = new StringBuffer();
167 x.append(Opcode.getOpcodeName(_code[0]));
168 x.append(' ');
169 for(int i = 1; i < _code.length; ++i) {
170 x.append(String.format("%02x", new Object[]{new Byte(_code[i])})).append(' ');
171 }
172 return x.toString();
173 }
174 }
175