1
3 package jminusminus;
4
5 import java.util.ArrayList;
6 import java.util.Hashtable;
7 import java.util.Iterator;
8 import java.util.Set;
9 import java.util.TreeMap;
10 import java.util.Map.Entry;
11
12 import static jminusminus.CLConstants.*;
13 import static jminusminus.CLConstants.Category.*;
14
15
21 abstract class CLInstruction {
22
25 protected int opcode;
26
27
30 protected String mnemonic;
31
32
36 protected int operandCount;
37
38
41 protected int pc;
42
43
46 protected int stackUnits;
47
48
52 protected int localVariableIndex;
53
54
60 public static final CLInsInfo[] instructionInfo = {
61 new CLInsInfo(NOP, "nop", 0, IRRELEVANT, 0, MISC),
62 new CLInsInfo(ACONST_NULL, "aconst_null", 0, IRRELEVANT, 1, LOAD_STORE1),
63 new CLInsInfo(ICONST_M1, "iconst_m1", 0, IRRELEVANT, 1, LOAD_STORE1),
64 new CLInsInfo(ICONST_0, "iconst_0", 0, IRRELEVANT, 1, LOAD_STORE1),
65 new CLInsInfo(ICONST_1, "iconst_1", 0, IRRELEVANT, 1, LOAD_STORE1),
66 new CLInsInfo(ICONST_2, "iconst_2", 0, IRRELEVANT, 1, LOAD_STORE1),
67 new CLInsInfo(ICONST_3, "iconst_3", 0, IRRELEVANT, 1, LOAD_STORE1),
68 new CLInsInfo(ICONST_4, "iconst_4", 0, IRRELEVANT, 1, LOAD_STORE1),
69 new CLInsInfo(ICONST_5, "iconst_5", 0, IRRELEVANT, 1, LOAD_STORE1),
70 new CLInsInfo(LCONST_0, "lconst_0", 0, IRRELEVANT, 2, LOAD_STORE1),
71 new CLInsInfo(LCONST_1, "lconst_1", 0, IRRELEVANT, 2, LOAD_STORE1),
72 new CLInsInfo(FCONST_0, "fconst_0", 0, IRRELEVANT, 1, LOAD_STORE1),
73 new CLInsInfo(FCONST_1, "fconst_1", 0, IRRELEVANT, 1, LOAD_STORE1),
74 new CLInsInfo(FCONST_2, "fconst_2", 0, IRRELEVANT, 1, LOAD_STORE1),
75 new CLInsInfo(DCONST_0, "dconst_0", 0, IRRELEVANT, 2, LOAD_STORE1),
76 new CLInsInfo(DCONST_1, "dconst_1", 0, IRRELEVANT, 2, LOAD_STORE1),
77 new CLInsInfo(BIPUSH, "bipush", 1, IRRELEVANT, 1, LOAD_STORE3),
78 new CLInsInfo(SIPUSH, "sipush", 2, IRRELEVANT, 1, LOAD_STORE3),
79 new CLInsInfo(LDC, "ldc", 1, IRRELEVANT, 1, LOAD_STORE4),
80 new CLInsInfo(LDC_W, "ldc_w", 2, IRRELEVANT, 1, LOAD_STORE4),
81 new CLInsInfo(LDC2_W, "ldc2_w", 2, IRRELEVANT, 2, LOAD_STORE4),
82 new CLInsInfo(ILOAD, "iload", 1, DYNAMIC, 1, LOAD_STORE2),
83 new CLInsInfo(LLOAD, "lload", 1, DYNAMIC, 2, LOAD_STORE2),
84 new CLInsInfo(FLOAD, "fload", 1, DYNAMIC, 1, LOAD_STORE2),
85 new CLInsInfo(DLOAD, "dload", 1, DYNAMIC, 2, LOAD_STORE2),
86 new CLInsInfo(ALOAD, "aload", 1, DYNAMIC, 1, LOAD_STORE2),
87 new CLInsInfo(ILOAD_0, "iload_0", 0, 0, 1, LOAD_STORE1),
88 new CLInsInfo(ILOAD_1, "iload_1", 0, 1, 1, LOAD_STORE1),
89 new CLInsInfo(ILOAD_2, "iload_2", 0, 2, 1, LOAD_STORE1),
90 new CLInsInfo(ILOAD_3, "iload_3", 0, 3, 1, LOAD_STORE1),
91 new CLInsInfo(LLOAD_0, "lload_0", 0, 0, 2, LOAD_STORE1),
92 new CLInsInfo(LLOAD_1, "lload_1", 0, 1, 2, LOAD_STORE1),
93 new CLInsInfo(LLOAD_2, "lload_2", 0, 2, 2, LOAD_STORE1),
94 new CLInsInfo(LLOAD_3, "lload_3", 0, 3, 2, LOAD_STORE1),
95 new CLInsInfo(FLOAD_0, "fload_0", 0, 0, 1, LOAD_STORE1),
96 new CLInsInfo(FLOAD_1, "fload_1", 0, 1, 1, LOAD_STORE1),
97 new CLInsInfo(FLOAD_2, "fload_2", 0, 2, 1, LOAD_STORE1),
98 new CLInsInfo(FLOAD_3, "fload_3", 0, 3, 1, LOAD_STORE1),
99 new CLInsInfo(DLOAD_0, "dload_0", 0, 0, 2, LOAD_STORE1),
100 new CLInsInfo(DLOAD_1, "dload_1", 0, 1, 2, LOAD_STORE1),
101 new CLInsInfo(DLOAD_2, "dload_2", 0, 2, 2, LOAD_STORE1),
102 new CLInsInfo(DLOAD_3, "dload_3", 0, 3, 2, LOAD_STORE1),
103 new CLInsInfo(ALOAD_0, "aload_0", 0, 0, 1, LOAD_STORE1),
104 new CLInsInfo(ALOAD_1, "aload_1", 0, 1, 1, LOAD_STORE1),
105 new CLInsInfo(ALOAD_2, "aload_2", 0, 2, 1, LOAD_STORE1),
106 new CLInsInfo(ALOAD_3, "aload_3", 0, 3, 1, LOAD_STORE1),
107 new CLInsInfo(IALOAD, "iaload", 0, IRRELEVANT, -1, ARRAY2),
108 new CLInsInfo(LALOAD, "laload", 0, IRRELEVANT, 0, ARRAY2),
109 new CLInsInfo(FALOAD, "faload", 0, IRRELEVANT, -1, ARRAY2),
110 new CLInsInfo(DALOAD, "daload", 0, IRRELEVANT, 0, ARRAY2),
111 new CLInsInfo(AALOAD, "aaload", 0, IRRELEVANT, -1, ARRAY2),
112 new CLInsInfo(BALOAD, "baload", 0, IRRELEVANT, -1, ARRAY2),
113 new CLInsInfo(CALOAD, "caload", 0, IRRELEVANT, -1, ARRAY2),
114 new CLInsInfo(SALOAD, "saload", 0, IRRELEVANT, -1, ARRAY2),
115 new CLInsInfo(ISTORE, "istore", 1, DYNAMIC, -1, LOAD_STORE2),
116 new CLInsInfo(LSTORE, "lstore", 1, DYNAMIC, -2, LOAD_STORE2),
117 new CLInsInfo(FSTORE, "fstore", 1, DYNAMIC, -1, LOAD_STORE2),
118 new CLInsInfo(DSTORE, "dstore", 1, DYNAMIC, -2, LOAD_STORE2),
119 new CLInsInfo(ASTORE, "astore", 1, DYNAMIC, -1, LOAD_STORE2),
120 new CLInsInfo(ISTORE_0, "istore_0", 0, 0, -1, LOAD_STORE1),
121 new CLInsInfo(ISTORE_1, "istore_1", 0, 1, -1, LOAD_STORE1),
122 new CLInsInfo(ISTORE_2, "istore_2", 0, 2, -1, LOAD_STORE1),
123 new CLInsInfo(ISTORE_3, "istore_3", 0, 3, -1, LOAD_STORE1),
124 new CLInsInfo(LSTORE_0, "lstore_0", 0, 0, -2, LOAD_STORE1),
125 new CLInsInfo(LSTORE_1, "lstore_1", 0, 1, -2, LOAD_STORE1),
126 new CLInsInfo(LSTORE_2, "lstore_2", 0, 2, -2, LOAD_STORE1),
127 new CLInsInfo(LSTORE_3, "lstore_3", 0, 3, -2, LOAD_STORE1),
128 new CLInsInfo(FSTORE_0, "fstore_0", 0, 0, -1, LOAD_STORE1),
129 new CLInsInfo(FSTORE_1, "fstore_1", 0, 1, -1, LOAD_STORE1),
130 new CLInsInfo(FSTORE_2, "fstore_2", 0, 2, -1, LOAD_STORE1),
131 new CLInsInfo(FSTORE_3, "fstore_3", 0, 3, -1, LOAD_STORE1),
132 new CLInsInfo(DSTORE_0, "dstore_0", 0, 0, -2, LOAD_STORE1),
133 new CLInsInfo(DSTORE_1, "dstore_1", 0, 1, -2, LOAD_STORE1),
134 new CLInsInfo(DSTORE_2, "dstore_2", 0, 2, -2, LOAD_STORE1),
135 new CLInsInfo(DSTORE_3, "dstore_3", 0, 3, -2, LOAD_STORE1),
136 new CLInsInfo(ASTORE_0, "astore_0", 0, 0, -1, LOAD_STORE1),
137 new CLInsInfo(ASTORE_1, "astore_1", 0, 1, -1, LOAD_STORE1),
138 new CLInsInfo(ASTORE_2, "astore_2", 0, 2, -1, LOAD_STORE1),
139 new CLInsInfo(ASTORE_3, "astore_3", 0, 3, -1, LOAD_STORE1),
140 new CLInsInfo(IASTORE, "iastore", 0, IRRELEVANT, -3, ARRAY2),
141 new CLInsInfo(LASTORE, "lastore", 0, IRRELEVANT, -4, ARRAY2),
142 new CLInsInfo(FASTORE, "fastore", 0, IRRELEVANT, -3, ARRAY2),
143 new CLInsInfo(DASTORE, "dastore", 0, IRRELEVANT, -4, ARRAY2),
144 new CLInsInfo(AASTORE, "aastore", 0, IRRELEVANT, -3, ARRAY2),
145 new CLInsInfo(BASTORE, "bastore", 0, IRRELEVANT, -3, ARRAY2),
146 new CLInsInfo(CASTORE, "castore", 0, IRRELEVANT, -3, ARRAY2),
147 new CLInsInfo(SASTORE, "sastore", 0, IRRELEVANT, -3, ARRAY2),
148 new CLInsInfo(POP, "pop", 0, IRRELEVANT, -1, STACK),
149 new CLInsInfo(POP2, "pop2", 0, IRRELEVANT, -2, STACK),
150 new CLInsInfo(DUP, "dup", 0, IRRELEVANT, 1, STACK),
151 new CLInsInfo(DUP_X1, "dup_x1", 0, IRRELEVANT, 1, STACK),
152 new CLInsInfo(DUP_X2, "dup_x2", 0, IRRELEVANT, 1, STACK),
153 new CLInsInfo(DUP2, "dup2", 0, IRRELEVANT, 2, STACK),
154 new CLInsInfo(DUP2_X1, "dup2_x1", 0, IRRELEVANT, 2, STACK),
155 new CLInsInfo(DUP2_X2, "dup2_x2", 0, IRRELEVANT, 2, STACK),
156 new CLInsInfo(SWAP, "swap", 0, IRRELEVANT, 0, STACK),
157 new CLInsInfo(IADD, "iadd", 0, IRRELEVANT, -1, ARITHMETIC1),
158 new CLInsInfo(LADD, "ladd", 0, IRRELEVANT, -2, ARITHMETIC1),
159 new CLInsInfo(FADD, "fadd", 0, IRRELEVANT, -1, ARITHMETIC1),
160 new CLInsInfo(DADD, "dadd", 0, IRRELEVANT, -2, ARITHMETIC1),
161 new CLInsInfo(ISUB, "isub", 0, IRRELEVANT, -1, ARITHMETIC1),
162 new CLInsInfo(LSUB, "lsub", 0, IRRELEVANT, -2, ARITHMETIC1),
163 new CLInsInfo(FSUB, "fsub", 0, IRRELEVANT, -1, ARITHMETIC1),
164 new CLInsInfo(DSUB, "dsub", 0, IRRELEVANT, -2, ARITHMETIC1),
165 new CLInsInfo(IMUL, "imul", 0, IRRELEVANT, -1, ARITHMETIC1),
166 new CLInsInfo(LMUL, "lmul", 0, IRRELEVANT, -2, ARITHMETIC1),
167 new CLInsInfo(FMUL, "fmul", 0, IRRELEVANT, -1, ARITHMETIC1),
168 new CLInsInfo(DMUL, "dmul", 0, IRRELEVANT, -2, ARITHMETIC1),
169 new CLInsInfo(IDIV, "idiv", 0, IRRELEVANT, -1, ARITHMETIC1),
170 new CLInsInfo(LDIV, "ldiv", 0, IRRELEVANT, -2, ARITHMETIC1),
171 new CLInsInfo(FDIV, "fdiv", 0, IRRELEVANT, -1, ARITHMETIC1),
172 new CLInsInfo(DDIV, "ddiv", 0, IRRELEVANT, -2, ARITHMETIC1),
173 new CLInsInfo(IREM, "irem", 0, IRRELEVANT, -1, ARITHMETIC1),
174 new CLInsInfo(LREM, "lrem", 0, IRRELEVANT, -2, ARITHMETIC1),
175 new CLInsInfo(FREM, "frem", 0, IRRELEVANT, -1, ARITHMETIC1),
176 new CLInsInfo(DREM, "drem", 0, IRRELEVANT, -2, ARITHMETIC1),
177 new CLInsInfo(INEG, "ineg", 0, IRRELEVANT, 0, ARITHMETIC1),
178 new CLInsInfo(LNEG, "lneg", 0, IRRELEVANT, 0, ARITHMETIC1),
179 new CLInsInfo(FNEG, "fneg", 0, IRRELEVANT, 0, ARITHMETIC1),
180 new CLInsInfo(DNEG, "dneg", 0, IRRELEVANT, 0, ARITHMETIC1),
181 new CLInsInfo(ISHL, "ishl", 0, IRRELEVANT, -1, BIT),
182 new CLInsInfo(LSHL, "lshl", 0, IRRELEVANT, -2, BIT),
183 new CLInsInfo(ISHR, "ishr", 0, IRRELEVANT, -1, BIT),
184 new CLInsInfo(LSHR, "lshr", 0, IRRELEVANT, -2, BIT),
185 new CLInsInfo(IUSHR, "iushr", 0, IRRELEVANT, -1, BIT),
186 new CLInsInfo(LUSHR, "lushr", 0, IRRELEVANT, -2, BIT),
187 new CLInsInfo(IAND, "iand", 0, IRRELEVANT, -1, BIT),
188 new CLInsInfo(LAND, "land", 0, IRRELEVANT, -2, BIT),
189 new CLInsInfo(IOR, "ior", 0, IRRELEVANT, -1, BIT),
190 new CLInsInfo(LOR, "lor", 0, IRRELEVANT, -2, BIT),
191 new CLInsInfo(IXOR, "ixor", 0, IRRELEVANT, -1, BIT),
192 new CLInsInfo(LXOR, "lxor", 0, IRRELEVANT, -2, BIT),
193 new CLInsInfo(IINC, "iinc", 2, DYNAMIC, 0, ARITHMETIC2),
194 new CLInsInfo(I2L, "i2l", 0, IRRELEVANT, 1, CONVERSION),
195 new CLInsInfo(I2F, "i2f", 0, IRRELEVANT, 0, CONVERSION),
196 new CLInsInfo(I2D, "i2d", 0, IRRELEVANT, 1, CONVERSION),
197 new CLInsInfo(L2I, "l2i", 0, IRRELEVANT, -1, CONVERSION),
198 new CLInsInfo(L2F, "l2f", 0, IRRELEVANT, -1, CONVERSION),
199 new CLInsInfo(L2D, "l2d", 0, IRRELEVANT, 0, CONVERSION),
200 new CLInsInfo(F2I, "f2i", 0, IRRELEVANT, 0, CONVERSION),
201 new CLInsInfo(F2L, "f2l", 0, IRRELEVANT, 1, CONVERSION),
202 new CLInsInfo(F2D, "f2d", 0, IRRELEVANT, 1, CONVERSION),
203 new CLInsInfo(D2I, "d2i", 0, IRRELEVANT, -1, CONVERSION),
204 new CLInsInfo(D2L, "d2l", 0, IRRELEVANT, 0, CONVERSION),
205 new CLInsInfo(D2F, "d2f", 0, IRRELEVANT, -1, CONVERSION),
206 new CLInsInfo(I2B, "i2b", 0, IRRELEVANT, 0, CONVERSION),
207 new CLInsInfo(I2C, "i2c", 0, IRRELEVANT, 0, CONVERSION),
208 new CLInsInfo(I2S, "i2s", 0, IRRELEVANT, 0, CONVERSION),
209 new CLInsInfo(LCMP, "lcmp", 0, IRRELEVANT, -3, COMPARISON),
210 new CLInsInfo(FCMPL, "fcmpl", 0, IRRELEVANT, -1, COMPARISON),
211 new CLInsInfo(FCMPG, "fcmpg", 0, IRRELEVANT, -1, COMPARISON),
212 new CLInsInfo(DCMPL, "dcmpl", 0, IRRELEVANT, -3, COMPARISON),
213 new CLInsInfo(DCMPG, "dcmpg", 0, IRRELEVANT, -3, COMPARISON),
214 new CLInsInfo(IFEQ, "ifeq", 2, IRRELEVANT, -1, FLOW_CONTROL1),
215 new CLInsInfo(IFNE, "ifne", 2, IRRELEVANT, -1, FLOW_CONTROL1),
216 new CLInsInfo(IFLT, "iflt", 2, IRRELEVANT, -1, FLOW_CONTROL1),
217 new CLInsInfo(IFGE, "ifge", 2, IRRELEVANT, -1, FLOW_CONTROL1),
218 new CLInsInfo(IFGT, "ifgt", 2, IRRELEVANT, -1, FLOW_CONTROL1),
219 new CLInsInfo(IFLE, "ifle", 2, IRRELEVANT, -1, FLOW_CONTROL1),
220 new CLInsInfo(IF_ICMPEQ, "if_icmpeq", 2, IRRELEVANT, -2, FLOW_CONTROL1),
221 new CLInsInfo(IF_ICMPNE, "if_icmpne", 2, IRRELEVANT, -2, FLOW_CONTROL1),
222 new CLInsInfo(IF_ICMPLT, "if_icmplt", 2, IRRELEVANT, -2, FLOW_CONTROL1),
223 new CLInsInfo(IF_ICMPGE, "if_icmpge", 2, IRRELEVANT, -2, FLOW_CONTROL1),
224 new CLInsInfo(IF_ICMPGT, "if_icmpgt", 2, IRRELEVANT, -2, FLOW_CONTROL1),
225 new CLInsInfo(IF_ICMPLE, "if_icmple", 2, IRRELEVANT, -2, FLOW_CONTROL1),
226 new CLInsInfo(IF_ACMPEQ, "if_acmpeq", 2, IRRELEVANT, -2, FLOW_CONTROL1),
227 new CLInsInfo(IF_ACMPNE, "if_acmpne", 2, IRRELEVANT, -2, FLOW_CONTROL1),
228 new CLInsInfo(GOTO, "goto", 2, IRRELEVANT, 0, FLOW_CONTROL1),
229 new CLInsInfo(JSR, "jsr", 2, IRRELEVANT, 1, FLOW_CONTROL1),
230 new CLInsInfo(RET, "ret", 1, IRRELEVANT, 0, FLOW_CONTROL2),
231 new CLInsInfo(TABLESWITCH, "tableswitch", DYNAMIC, IRRELEVANT, -1, FLOW_CONTROL3),
232 new CLInsInfo(LOOKUPSWITCH, "lookupswitch", DYNAMIC, IRRELEVANT, -1, FLOW_CONTROL4),
233 new CLInsInfo(IRETURN, "ireturn", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
234 new CLInsInfo(LRETURN, "lreturn", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
235 new CLInsInfo(FRETURN, "freturn", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
236 new CLInsInfo(DRETURN, "dreturn", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
237 new CLInsInfo(ARETURN, "areturn", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
238 new CLInsInfo(RETURN, "return", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
239 new CLInsInfo(GETSTATIC, "getstatic", 2, IRRELEVANT, DYNAMIC, FIELD),
240 new CLInsInfo(PUTSTATIC, "putstatic", 2, IRRELEVANT, DYNAMIC, FIELD),
241 new CLInsInfo(GETFIELD, "getfield", 2, IRRELEVANT, DYNAMIC, FIELD),
242 new CLInsInfo(PUTFIELD, "putfield", 2, IRRELEVANT, DYNAMIC, FIELD),
243 new CLInsInfo(INVOKEVIRTUAL, "invokevirtual", 2, IRRELEVANT, DYNAMIC, METHOD1),
244 new CLInsInfo(INVOKESPECIAL, "invokespecial", 2, IRRELEVANT, DYNAMIC, METHOD1),
245 new CLInsInfo(INVOKESTATIC, "invokestatic", 2, IRRELEVANT, DYNAMIC, METHOD1),
246 new CLInsInfo(INVOKEINTERFACE, "invokeinterface", 4, IRRELEVANT, DYNAMIC, METHOD1),
247 new CLInsInfo(INVOKEDYNAMIC, "invokedynamic", 2, IRRELEVANT, DYNAMIC, METHOD1),
248 new CLInsInfo(NEW, "new", 2, IRRELEVANT, 1, OBJECT),
249 new CLInsInfo(NEWARRAY, "newarray", 1, IRRELEVANT, 0, ARRAY1),
250 new CLInsInfo(ANEWARRAY, "anewarray", 2, IRRELEVANT, 0, ARRAY1),
251 new CLInsInfo(ARRAYLENGTH, "arraylength", 0, IRRELEVANT, 0, ARRAY2),
252 new CLInsInfo(ATHROW, "athrow", 0, IRRELEVANT, UNIT_SIZE_STACK, MISC),
253 new CLInsInfo(CHECKCAST, "checkcast", 2, IRRELEVANT, 0, OBJECT),
254 new CLInsInfo(INSTANCEOF, "instanceof", 2, IRRELEVANT, 0, OBJECT),
255 new CLInsInfo(MONITORENTER, "monitorenter", 0, IRRELEVANT, -1, MISC),
256 new CLInsInfo(MONITOREXIT, "monitorexit", 0, IRRELEVANT, -1, MISC),
257 new CLInsInfo(WIDE, "wide", 3, IRRELEVANT, 0, LOAD_STORE1),
258 new CLInsInfo(MULTIANEWARRAY, "multianewarray", 3, IRRELEVANT, 0, ARRAY3),
259 new CLInsInfo(IFNULL, "ifnull", 2, IRRELEVANT, -1, FLOW_CONTROL1),
260 new CLInsInfo(IFNONNULL, "ifnonnull", 2, IRRELEVANT, -1, FLOW_CONTROL1),
261 new CLInsInfo(GOTO_W, "goto_w", 4, IRRELEVANT, 0, FLOW_CONTROL1),
262 new CLInsInfo(JSR_W, "jsr_w", 4, IRRELEVANT, 1, FLOW_CONTROL1)};
263
264
270 public static boolean isValid(int opcode) {
271 return NOP <= opcode && opcode <= JSR_W;
272 }
273
274
279 public int opcode() {
280 return opcode;
281 }
282
283
288 public String mnemonic() {
289 return mnemonic;
290 }
291
292
297 public int operandCount() {
298 return operandCount;
299 }
300
301
306 public int pc() {
307 return pc;
308 }
309
310
315 public int stackUnits() {
316 return stackUnits;
317 }
318
319
324 public int localVariableIndex() {
325 return localVariableIndex;
326 }
327
328
333 public abstract ArrayList<Integer> toBytes();
334
335
342 protected int byteAt(int i, int byteNum) {
343 int j = 0, mask = 0xFF;
344 switch (byteNum) {
345 case 1: j = i & mask;
347 break;
348 case 2:
349 j = (i >> 8) & mask;
350 break;
351 case 3:
352 j = (i >> 16) & mask;
353 break;
354 case 4: j = (i >> 24) & mask;
356 break;
357 }
358 return j;
359 }
360 }
361
362
365 class CLObjectInstruction extends CLInstruction {
366 private int index;
368
369
376 public CLObjectInstruction(int opcode, int pc, int index) {
377 super.opcode = opcode;
378 super.pc = pc;
379 mnemonic = instructionInfo[opcode].mnemonic;
380 operandCount = instructionInfo[opcode].operandCount;
381 stackUnits = instructionInfo[opcode].stackUnits;
382 localVariableIndex = instructionInfo[opcode].localVariableIndex;
383 this.index = index;
384 }
385
386
389 public ArrayList<Integer> toBytes() {
390 ArrayList<Integer> bytes = new ArrayList<Integer>();
391 bytes.add(opcode);
392 bytes.add(byteAt(index, 2));
393 bytes.add(byteAt(index, 1));
394 return bytes;
395 }
396 }
397
398
401 class CLFieldInstruction extends CLInstruction {
402 private int index;
405
406
415 public CLFieldInstruction(int opcode, int pc, int index, int stackUnits) {
416 super.opcode = opcode;
417 super.pc = pc;
418 mnemonic = instructionInfo[opcode].mnemonic;
419 operandCount = instructionInfo[opcode].operandCount;
420 super.stackUnits = stackUnits;
421 localVariableIndex = instructionInfo[opcode].localVariableIndex;
422 this.index = index;
423 }
424
425
428 public ArrayList<Integer> toBytes() {
429 ArrayList<Integer> bytes = new ArrayList<Integer>();
430 bytes.add(opcode);
431 bytes.add(byteAt(index, 2));
432 bytes.add(byteAt(index, 1));
433 return bytes;
434 }
435 }
436
437
440 class CLMethodInstruction extends CLInstruction {
441 private int index;
444
445 private int nArgs;
447
448
457 public CLMethodInstruction(int opcode, int pc, int index, int stackUnits) {
458 super.opcode = opcode;
459 super.pc = pc;
460 mnemonic = instructionInfo[opcode].mnemonic;
461 operandCount = instructionInfo[opcode].operandCount;
462 super.stackUnits = stackUnits;
463 localVariableIndex = instructionInfo[opcode].localVariableIndex;
464 this.index = index;
465 }
466
467
473 public CLMethodInstruction(int opcode, int pc) {
474 super.opcode = opcode;
475 super.pc = pc;
476 mnemonic = instructionInfo[opcode].mnemonic;
477 operandCount = instructionInfo[opcode].operandCount;
478 stackUnits = instructionInfo[opcode].stackUnits;
479 localVariableIndex = instructionInfo[opcode].localVariableIndex;
480 }
481
482
487 public void setArgumentCount(int nArgs) {
488 this.nArgs = nArgs;
489 }
490
491
494 public ArrayList<Integer> toBytes() {
495 ArrayList<Integer> bytes = new ArrayList<Integer>();
496 bytes.add(opcode);
497 if (instructionInfo[opcode].category == METHOD1) {
498 bytes.add(byteAt(index, 2));
499 bytes.add(byteAt(index, 1));
500
501 if (opcode == INVOKEINTERFACE) {
504 bytes.add(byteAt(nArgs, 1));
505 bytes.add(0);
506 }
507 }
508 return bytes;
509 }
510 }
511
512
515 class CLArrayInstruction extends CLInstruction {
516 private int type;
519
520 private int dim;
522
523
530 public CLArrayInstruction(int opcode, int pc, int type) {
531 super.opcode = opcode;
532 super.pc = pc;
533 mnemonic = instructionInfo[opcode].mnemonic;
534 operandCount = instructionInfo[opcode].operandCount;
535 stackUnits = instructionInfo[opcode].stackUnits;
536 localVariableIndex = instructionInfo[opcode].localVariableIndex;
537 this.type = type;
538 }
539
540
548 public CLArrayInstruction(int opcode, int pc, int type, int dim) {
549 super.opcode = opcode;
550 super.pc = pc;
551 mnemonic = instructionInfo[opcode].mnemonic;
552 operandCount = instructionInfo[opcode].operandCount;
553 stackUnits = instructionInfo[opcode].stackUnits;
554 localVariableIndex = instructionInfo[opcode].localVariableIndex;
555 this.type = type;
556 this.dim = dim;
557 }
558
559
565 public CLArrayInstruction(int opcode, int pc) {
566 super.opcode = opcode;
567 super.pc = pc;
568 mnemonic = instructionInfo[opcode].mnemonic;
569 operandCount = instructionInfo[opcode].operandCount;
570 stackUnits = instructionInfo[opcode].stackUnits;
571 localVariableIndex = instructionInfo[opcode].localVariableIndex;
572 }
573
574
577 public ArrayList<Integer> toBytes() {
578 ArrayList<Integer> bytes = new ArrayList<Integer>();
579 bytes.add(opcode);
580 switch (opcode) {
581 case NEWARRAY:
582 bytes.add(byteAt(type, 1));
583 break;
584 case ANEWARRAY:
585 bytes.add(byteAt(type, 2));
586 bytes.add(byteAt(type, 1));
587 break;
588 case MULTIANEWARRAY:
589 bytes.add(byteAt(type, 2));
590 bytes.add(byteAt(type, 1));
591 bytes.add(byteAt(dim, 1));
592 break;
593 }
594 return bytes;
595 }
596 }
597
598
601 class CLArithmeticInstruction extends CLInstruction {
602 private boolean isWidened;
604
605 private int constVal;
607
608
614 public CLArithmeticInstruction(int opcode, int pc) {
615 super.opcode = opcode;
616 super.pc = pc;
617 mnemonic = instructionInfo[opcode].mnemonic;
618 operandCount = instructionInfo[opcode].operandCount;
619 stackUnits = instructionInfo[opcode].stackUnits;
620 localVariableIndex = instructionInfo[opcode].localVariableIndex;
621 }
622
623
633 public CLArithmeticInstruction(int opcode, int pc, int localVariableIndex, int constVal,
634 boolean isWidened) {
635 super.opcode = opcode;
636 super.pc = pc;
637 super.localVariableIndex = localVariableIndex;
638 mnemonic = instructionInfo[opcode].mnemonic;
639 operandCount = instructionInfo[opcode].operandCount;
640 stackUnits = instructionInfo[opcode].stackUnits;
641 this.constVal = constVal;
642 this.isWidened = isWidened;
643 }
644
645
648 public ArrayList<Integer> toBytes() {
649 ArrayList<Integer> bytes = new ArrayList<Integer>();
650 bytes.add(opcode);
651 if (opcode == IINC) {
652 if (isWidened) {
653 bytes.add(byteAt(localVariableIndex, 2));
654 bytes.add(byteAt(localVariableIndex, 1));
655 bytes.add(byteAt(constVal, 2));
656 bytes.add(byteAt(constVal, 1));
657 } else {
658 bytes.add(byteAt(localVariableIndex, 1));
659 bytes.add(byteAt(constVal, 1));
660 }
661 }
662 return bytes;
663 }
664 }
665
666
669 class CLBitInstruction extends CLInstruction {
670
676 public CLBitInstruction(int opcode, int pc) {
677 super.opcode = opcode;
678 super.pc = pc;
679 mnemonic = instructionInfo[opcode].mnemonic;
680 operandCount = instructionInfo[opcode].operandCount;
681 stackUnits = instructionInfo[opcode].stackUnits;
682 localVariableIndex = instructionInfo[opcode].localVariableIndex;
683 }
684
685
688 public ArrayList<Integer> toBytes() {
689 ArrayList<Integer> bytes = new ArrayList<Integer>();
690 bytes.add(opcode);
691 return bytes;
692 }
693 }
694
695
698 class CLComparisonInstruction extends CLInstruction {
699
705 public CLComparisonInstruction(int opcode, int pc) {
706 super.opcode = opcode;
707 super.pc = pc;
708 mnemonic = instructionInfo[opcode].mnemonic;
709 operandCount = instructionInfo[opcode].operandCount;
710 stackUnits = instructionInfo[opcode].stackUnits;
711 localVariableIndex = instructionInfo[opcode].localVariableIndex;
712 }
713
714
717 public ArrayList<Integer> toBytes() {
718 ArrayList<Integer> bytes = new ArrayList<Integer>();
719 bytes.add(opcode);
720 return bytes;
721 }
722 }
723
724
727 class CLConversionInstruction extends CLInstruction {
728
734 public CLConversionInstruction(int opcode, int pc) {
735 super.opcode = opcode;
736 super.pc = pc;
737 mnemonic = instructionInfo[opcode].mnemonic;
738 operandCount = instructionInfo[opcode].operandCount;
739 stackUnits = instructionInfo[opcode].stackUnits;
740 localVariableIndex = instructionInfo[opcode].localVariableIndex;
741 }
742
743
746 public ArrayList<Integer> toBytes() {
747 ArrayList<Integer> bytes = new ArrayList<Integer>();
748 bytes.add(opcode);
749 return bytes;
750 }
751 }
752
753
756 class CLFlowControlInstruction extends CLInstruction {
757 private String jumpToLabel;
759
760 private int jumpToOffset;
762
763 private int index;
765
766 private boolean isWidened;
768
769 private int pad;
772
773 private String defaultLabel;
775
776 private int defaultOffset;
778
779 private int numPairs;
781
782 private TreeMap<Integer, String> matchLabelPairs;
784
785 private TreeMap<Integer, Integer> matchOffsetPairs;
787
788 private int low;
790
791 private int high;
793
794 private ArrayList<String> labels;
797
798 private ArrayList<Integer> offsets;
800
801
809 public CLFlowControlInstruction(int opcode, int pc, String jumpToLabel) {
810 super.opcode = opcode;
811 super.pc = pc;
812 mnemonic = instructionInfo[opcode].mnemonic;
813 operandCount = instructionInfo[opcode].operandCount;
814 stackUnits = instructionInfo[opcode].stackUnits;
815 localVariableIndex = instructionInfo[opcode].localVariableIndex;
816 this.jumpToLabel = jumpToLabel;
817 }
818
819
827 public CLFlowControlInstruction(int pc, int index, boolean isWidened) {
828 super.opcode = RET;
829 super.pc = pc;
830 mnemonic = instructionInfo[opcode].mnemonic;
831 operandCount = instructionInfo[opcode].operandCount;
832 stackUnits = instructionInfo[opcode].stackUnits;
833 localVariableIndex = instructionInfo[opcode].localVariableIndex;
834 this.index = index;
835 this.isWidened = isWidened;
836 }
837
838
849 public CLFlowControlInstruction(int opcode, int pc, String defaultLabel, int low, int high,
850 ArrayList<String> labels) {
851 super.opcode = opcode;
852 super.pc = pc;
853 mnemonic = instructionInfo[opcode].mnemonic;
854 stackUnits = instructionInfo[opcode].stackUnits;
855 localVariableIndex = instructionInfo[opcode].localVariableIndex;
856 this.defaultLabel = defaultLabel;
857 this.low = low;
858 this.high = high;
859 this.labels = labels;
860 pad = 4 - ((pc + 1) % 4);
861 if (pad == 4) {
862 pad = 0;
863 }
864 operandCount = pad + 12 + 4 * labels.size();
865 }
866
867
876 public CLFlowControlInstruction(int opcode, int pc, String defaultLabel, int numPairs,
877 TreeMap<Integer, String> matchLabelPairs) {
878 super.opcode = opcode;
879 super.pc = pc;
880 mnemonic = instructionInfo[opcode].mnemonic;
881 stackUnits = instructionInfo[opcode].stackUnits;
882 localVariableIndex = instructionInfo[opcode].localVariableIndex;
883 this.defaultLabel = defaultLabel;
884 this.numPairs = numPairs;
885 this.matchLabelPairs = matchLabelPairs;
886 pad = 4 - ((pc + 1) % 4);
887 if (pad == 4) {
888 pad = 0;
889 }
890 operandCount = pad + 8 + 8 * numPairs;
891 }
892
893
901 public boolean resolveLabels(Hashtable<String, Integer> labelToPC) {
902 boolean allLabelsResolved = true;
903 if (instructionInfo[opcode].category == FLOW_CONTROL1) {
904 if (labelToPC.containsKey(jumpToLabel)) {
905 jumpToOffset = labelToPC.get(jumpToLabel) - pc;
906 } else {
907 jumpToOffset = operandCount;
908 allLabelsResolved = false;
909 }
910 } else if (opcode == LOOKUPSWITCH) {
911 if (labelToPC.containsKey(defaultLabel)) {
912 defaultOffset = labelToPC.get(defaultLabel) - pc;
913 } else {
914 defaultOffset = operandCount;
915 allLabelsResolved = false;
916 }
917 matchOffsetPairs = new TreeMap<Integer, Integer>();
918 Set<Entry<Integer, String>> matches = matchLabelPairs.entrySet();
919 Iterator<Entry<Integer, String>> iter = matches.iterator();
920 while (iter.hasNext()) {
921 Entry<Integer, String> entry = iter.next();
922 int match = entry.getKey();
923 String label = entry.getValue();
924 if (labelToPC.containsKey(label)) {
925 matchOffsetPairs.put(match, labelToPC.get(label) - pc);
926 } else {
927 matchOffsetPairs.put(match, operandCount);
928 allLabelsResolved = false;
929 }
930 }
931 } else if (opcode == TABLESWITCH) {
932 if (labelToPC.containsKey(defaultLabel)) {
933 defaultOffset = labelToPC.get(defaultLabel) - pc;
934 } else {
935 defaultOffset = operandCount;
936 allLabelsResolved = false;
937 }
938 offsets = new ArrayList<Integer>();
939 for (String label : labels) {
940 if (labelToPC.containsKey(label)) {
941 offsets.add(labelToPC.get(label) - pc);
942 } else {
943 offsets.add(operandCount);
944 allLabelsResolved = false;
945 }
946 }
947 }
948 return allLabelsResolved;
949 }
950
951
956 public int jumpToOffset() {
957 return jumpToOffset;
958 }
959
960
963 public ArrayList<Integer> toBytes() {
964 ArrayList<Integer> bytes = new ArrayList<Integer>();
965 bytes.add(opcode);
966 switch (opcode) {
967 case RET:
968 if (isWidened) {
969 bytes.add(byteAt(index, 2));
970 bytes.add(byteAt(index, 1));
971 } else {
972 bytes.add(byteAt(index, 1));
973 }
974 break;
975 case TABLESWITCH:
976 for (int i = 0; i < pad; i++) {
977 bytes.add(0);
978 }
979 bytes.add(byteAt(defaultOffset, 4));
980 bytes.add(byteAt(defaultOffset, 3));
981 bytes.add(byteAt(defaultOffset, 2));
982 bytes.add(byteAt(defaultOffset, 1));
983 bytes.add(byteAt(low, 4));
984 bytes.add(byteAt(low, 3));
985 bytes.add(byteAt(low, 2));
986 bytes.add(byteAt(low, 1));
987 bytes.add(byteAt(high, 4));
988 bytes.add(byteAt(high, 3));
989 bytes.add(byteAt(high, 2));
990 bytes.add(byteAt(high, 1));
991 for (int i = 0; i < offsets.size(); i++) {
992 int jumpOffset = offsets.get(i);
993 bytes.add(byteAt(jumpOffset, 4));
994 bytes.add(byteAt(jumpOffset, 3));
995 bytes.add(byteAt(jumpOffset, 2));
996 bytes.add(byteAt(jumpOffset, 1));
997 }
998 break;
999 case LOOKUPSWITCH:
1000 for (int i = 0; i < pad; i++) {
1001 bytes.add(0);
1002 }
1003 bytes.add(byteAt(defaultOffset, 4));
1004 bytes.add(byteAt(defaultOffset, 3));
1005 bytes.add(byteAt(defaultOffset, 2));
1006 bytes.add(byteAt(defaultOffset, 1));
1007 bytes.add(byteAt(numPairs, 4));
1008 bytes.add(byteAt(numPairs, 3));
1009 bytes.add(byteAt(numPairs, 2));
1010 bytes.add(byteAt(numPairs, 1));
1011 Set<Entry<Integer, Integer>> matches = matchOffsetPairs.entrySet();
1012 Iterator<Entry<Integer, Integer>> iter = matches.iterator();
1013 while (iter.hasNext()) {
1014 Entry<Integer, Integer> entry = iter.next();
1015 int match = entry.getKey();
1016 int offset = entry.getValue();
1017 bytes.add(byteAt(match, 4));
1018 bytes.add(byteAt(match, 3));
1019 bytes.add(byteAt(match, 2));
1020 bytes.add(byteAt(match, 1));
1021 bytes.add(byteAt(offset, 4));
1022 bytes.add(byteAt(offset, 3));
1023 bytes.add(byteAt(offset, 2));
1024 bytes.add(byteAt(offset, 1));
1025 }
1026 break;
1027 case GOTO_W:
1028 case JSR_W:
1029 bytes.add(byteAt(jumpToOffset, 4));
1030 bytes.add(byteAt(jumpToOffset, 3));
1031 bytes.add(byteAt(jumpToOffset, 2));
1032 bytes.add(byteAt(jumpToOffset, 1));
1033 break;
1034 default:
1035 bytes.add(byteAt(jumpToOffset, 2));
1036 bytes.add(byteAt(jumpToOffset, 1));
1037 }
1038 return bytes;
1039 }
1040}
1041
1042
1045class CLLoadStoreInstruction extends CLInstruction {
1046 private boolean isWidened;
1049
1050 private int constVal;
1053
1054
1060 public CLLoadStoreInstruction(int opcode, int pc) {
1061 super.opcode = opcode;
1062 super.pc = pc;
1063 mnemonic = instructionInfo[opcode].mnemonic;
1064 operandCount = instructionInfo[opcode].operandCount;
1065 stackUnits = instructionInfo[opcode].stackUnits;
1066 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1067 }
1068
1069
1078 public CLLoadStoreInstruction(int opcode, int pc, int localVariableIndex, boolean isWidened) {
1079 super.opcode = opcode;
1080 super.pc = pc;
1081 mnemonic = instructionInfo[opcode].mnemonic;
1082 operandCount = instructionInfo[opcode].operandCount;
1083 stackUnits = instructionInfo[opcode].stackUnits;
1084 super.localVariableIndex = localVariableIndex;
1085 this.isWidened = isWidened;
1086 }
1087
1088
1097 public CLLoadStoreInstruction(int opcode, int pc, int constVal) {
1098 super.opcode = opcode;
1099 super.pc = pc;
1100 mnemonic = instructionInfo[opcode].mnemonic;
1101 operandCount = instructionInfo[opcode].operandCount;
1102 stackUnits = instructionInfo[opcode].stackUnits;
1103 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1104 this.constVal = constVal;
1105 }
1106
1107
1110 public ArrayList<Integer> toBytes() {
1111 ArrayList<Integer> bytes = new ArrayList<Integer>();
1112 bytes.add(opcode);
1113 if (instructionInfo[opcode].operandCount > 0) {
1114 if (localVariableIndex != IRRELEVANT) {
1115 if (isWidened) {
1116 bytes.add(byteAt(localVariableIndex, 2));
1117 }
1118 bytes.add(byteAt(localVariableIndex, 1));
1119 } else {
1120 switch (opcode) {
1121 case BIPUSH:
1122 case LDC:
1123 bytes.add(byteAt(constVal, 1));
1124 break;
1125 case SIPUSH:
1126 case LDC_W:
1127 case LDC2_W:
1128 bytes.add(byteAt(constVal, 2));
1129 bytes.add(byteAt(constVal, 1));
1130 }
1131 }
1132 }
1133 return bytes;
1134 }
1135}
1136
1137
1140class CLStackInstruction extends CLInstruction {
1141
1147 public CLStackInstruction(int opcode, int pc) {
1148 super.opcode = opcode;
1149 super.pc = pc;
1150 mnemonic = instructionInfo[opcode].mnemonic;
1151 operandCount = instructionInfo[opcode].operandCount;
1152 stackUnits = instructionInfo[opcode].stackUnits;
1153 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1154 }
1155
1156
1159 public ArrayList<Integer> toBytes() {
1160 ArrayList<Integer> bytes = new ArrayList<Integer>();
1161 bytes.add(opcode);
1162 return bytes;
1163 }
1164}
1165
1166
1169class CLMiscInstruction extends CLInstruction {
1170
1176 public CLMiscInstruction(int opcode, int pc) {
1177 super.opcode = opcode;
1178 super.pc = pc;
1179 mnemonic = instructionInfo[opcode].mnemonic;
1180 operandCount = instructionInfo[opcode].operandCount;
1181 stackUnits = instructionInfo[opcode].stackUnits;
1182 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1183 }
1184
1185
1188 public ArrayList<Integer> toBytes() {
1189 ArrayList<Integer> bytes = new ArrayList<Integer>();
1190 bytes.add(opcode);
1191 return bytes;
1192 }
1193}
1194
1195
1198class CLInsInfo {
1199
1202 public int opcode;
1203
1204
1207 public String mnemonic;
1208
1209
1212 public int operandCount;
1213
1214
1217 public int stackUnits;
1218
1219
1223 public int localVariableIndex;
1224
1225
1228 public Category category;
1229
1230
1241 public CLInsInfo(int opcode, String mnemonic, int operandCount, int localVariableIndex,
1242 int stackUnits, Category category) {
1243 this.opcode = opcode;
1244 this.mnemonic = mnemonic;
1245 this.operandCount = operandCount;
1246 this.localVariableIndex = localVariableIndex;
1247 this.stackUnits = stackUnits;
1248 this.category = category;
1249 }
1250}
1251