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 import static jminusminus.CLConstants.*;
12 import static jminusminus.CLConstants.Category.*;
13
14
21
22 abstract class CLInstruction {
23
24
25 protected int opcode;
26
27
28 protected String mnemonic;
29
30
34 protected int operandCount;
35
36
40 protected int pc;
41
42
46 protected int stackUnits;
47
48
52 protected int localVariableIndex;
53
54
61 public static final CLInsInfo[] instructionInfo = {
62 new CLInsInfo(NOP, "nop", 0, IRRELEVANT, 0, MISC),
63 new CLInsInfo(ACONST_NULL, "aconst_null", 0, IRRELEVANT, 1,
64 LOAD_STORE1),
65 new CLInsInfo(ICONST_M1, "iconst_m1", 0, IRRELEVANT, 1, LOAD_STORE1),
66 new CLInsInfo(ICONST_0, "iconst_0", 0, IRRELEVANT, 1, LOAD_STORE1),
67 new CLInsInfo(ICONST_1, "iconst_1", 0, IRRELEVANT, 1, LOAD_STORE1),
68 new CLInsInfo(ICONST_2, "iconst_2", 0, IRRELEVANT, 1, LOAD_STORE1),
69 new CLInsInfo(ICONST_3, "iconst_3", 0, IRRELEVANT, 1, LOAD_STORE1),
70 new CLInsInfo(ICONST_4, "iconst_4", 0, IRRELEVANT, 1, LOAD_STORE1),
71 new CLInsInfo(ICONST_5, "iconst_5", 0, IRRELEVANT, 1, LOAD_STORE1),
72 new CLInsInfo(LCONST_0, "lconst_0", 0, IRRELEVANT, 2, LOAD_STORE1),
73 new CLInsInfo(LCONST_1, "lconst_1", 0, IRRELEVANT, 2, LOAD_STORE1),
74 new CLInsInfo(FCONST_0, "fconst_0", 0, IRRELEVANT, 1, LOAD_STORE1),
75 new CLInsInfo(FCONST_1, "fconst_1", 0, IRRELEVANT, 1, LOAD_STORE1),
76 new CLInsInfo(FCONST_2, "fconst_2", 0, IRRELEVANT, 1, LOAD_STORE1),
77 new CLInsInfo(DCONST_0, "dconst_0", 0, IRRELEVANT, 2, LOAD_STORE1),
78 new CLInsInfo(DCONST_1, "dconst_1", 0, IRRELEVANT, 2, LOAD_STORE1),
79 new CLInsInfo(BIPUSH, "bipush", 1, IRRELEVANT, 1, LOAD_STORE3),
80 new CLInsInfo(SIPUSH, "sipush", 2, IRRELEVANT, 1, LOAD_STORE3),
81 new CLInsInfo(LDC, "ldc", 1, IRRELEVANT, 1, LOAD_STORE4),
82 new CLInsInfo(LDC_W, "ldc_w", 2, IRRELEVANT, 1, LOAD_STORE4),
83 new CLInsInfo(LDC2_W, "ldc2_w", 2, IRRELEVANT, 2, LOAD_STORE4),
84 new CLInsInfo(ILOAD, "iload", 1, DYNAMIC, 1, LOAD_STORE2),
85 new CLInsInfo(LLOAD, "lload", 1, DYNAMIC, 2, LOAD_STORE2),
86 new CLInsInfo(FLOAD, "fload", 1, DYNAMIC, 1, LOAD_STORE2),
87 new CLInsInfo(DLOAD, "dload", 1, DYNAMIC, 2, LOAD_STORE2),
88 new CLInsInfo(ALOAD, "aload", 1, DYNAMIC, 1, LOAD_STORE2),
89 new CLInsInfo(ILOAD_0, "iload_0", 0, 0, 1, LOAD_STORE1),
90 new CLInsInfo(ILOAD_1, "iload_1", 0, 1, 1, LOAD_STORE1),
91 new CLInsInfo(ILOAD_2, "iload_2", 0, 2, 1, LOAD_STORE1),
92 new CLInsInfo(ILOAD_3, "iload_3", 0, 3, 1, LOAD_STORE1),
93 new CLInsInfo(LLOAD_0, "lload_0", 0, 0, 2, LOAD_STORE1),
94 new CLInsInfo(LLOAD_1, "lload_1", 0, 1, 2, LOAD_STORE1),
95 new CLInsInfo(LLOAD_2, "lload_2", 0, 2, 2, LOAD_STORE1),
96 new CLInsInfo(LLOAD_3, "lload_3", 0, 3, 2, LOAD_STORE1),
97 new CLInsInfo(FLOAD_0, "fload_0", 0, 0, 1, LOAD_STORE1),
98 new CLInsInfo(FLOAD_1, "fload_1", 0, 1, 1, LOAD_STORE1),
99 new CLInsInfo(FLOAD_2, "fload_2", 0, 2, 1, LOAD_STORE1),
100 new CLInsInfo(FLOAD_3, "fload_3", 0, 3, 1, LOAD_STORE1),
101 new CLInsInfo(DLOAD_0, "dload_0", 0, 0, 2, LOAD_STORE1),
102 new CLInsInfo(DLOAD_1, "dload_1", 0, 1, 2, LOAD_STORE1),
103 new CLInsInfo(DLOAD_2, "dload_2", 0, 2, 2, LOAD_STORE1),
104 new CLInsInfo(DLOAD_3, "dload_3", 0, 3, 2, LOAD_STORE1),
105 new CLInsInfo(ALOAD_0, "aload_0", 0, 0, 1, LOAD_STORE1),
106 new CLInsInfo(ALOAD_1, "aload_1", 0, 1, 1, LOAD_STORE1),
107 new CLInsInfo(ALOAD_2, "aload_2", 0, 2, 1, LOAD_STORE1),
108 new CLInsInfo(ALOAD_3, "aload_3", 0, 3, 1, LOAD_STORE1),
109 new CLInsInfo(IALOAD, "iaload", 0, IRRELEVANT, -1, ARRAY2),
110 new CLInsInfo(LALOAD, "laload", 0, IRRELEVANT, 0, ARRAY2),
111 new CLInsInfo(FALOAD, "faload", 0, IRRELEVANT, -1, ARRAY2),
112 new CLInsInfo(DALOAD, "daload", 0, IRRELEVANT, 0, ARRAY2),
113 new CLInsInfo(AALOAD, "aaload", 0, IRRELEVANT, -1, ARRAY2),
114 new CLInsInfo(BALOAD, "baload", 0, IRRELEVANT, -1, ARRAY2),
115 new CLInsInfo(CALOAD, "caload", 0, IRRELEVANT, -1, ARRAY2),
116 new CLInsInfo(SALOAD, "saload", 0, IRRELEVANT, -1, ARRAY2),
117 new CLInsInfo(ISTORE, "istore", 1, DYNAMIC, -1, LOAD_STORE2),
118 new CLInsInfo(LSTORE, "lstore", 1, DYNAMIC, -2, LOAD_STORE2),
119 new CLInsInfo(FSTORE, "fstore", 1, DYNAMIC, -1, LOAD_STORE2),
120 new CLInsInfo(DSTORE, "dstore", 1, DYNAMIC, -2, LOAD_STORE2),
121 new CLInsInfo(ASTORE, "astore", 1, DYNAMIC, -1, LOAD_STORE2),
122 new CLInsInfo(ISTORE_0, "istore_0", 0, 0, -1, LOAD_STORE1),
123 new CLInsInfo(ISTORE_1, "istore_1", 0, 1, -1, LOAD_STORE1),
124 new CLInsInfo(ISTORE_2, "istore_2", 0, 2, -1, LOAD_STORE1),
125 new CLInsInfo(ISTORE_3, "istore_3", 0, 3, -1, LOAD_STORE1),
126 new CLInsInfo(LSTORE_0, "lstore_0", 0, 0, -2, LOAD_STORE1),
127 new CLInsInfo(LSTORE_1, "lstore_1", 0, 1, -2, LOAD_STORE1),
128 new CLInsInfo(LSTORE_2, "lstore_2", 0, 2, -2, LOAD_STORE1),
129 new CLInsInfo(LSTORE_3, "lstore_3", 0, 3, -2, LOAD_STORE1),
130 new CLInsInfo(FSTORE_0, "fstore_0", 0, 0, -1, LOAD_STORE1),
131 new CLInsInfo(FSTORE_1, "fstore_1", 0, 1, -1, LOAD_STORE1),
132 new CLInsInfo(FSTORE_2, "fstore_2", 0, 2, -1, LOAD_STORE1),
133 new CLInsInfo(FSTORE_3, "fstore_3", 0, 3, -1, LOAD_STORE1),
134 new CLInsInfo(DSTORE_0, "dstore_0", 0, 0, -2, LOAD_STORE1),
135 new CLInsInfo(DSTORE_1, "dstore_1", 0, 1, -2, LOAD_STORE1),
136 new CLInsInfo(DSTORE_2, "dstore_2", 0, 2, -2, LOAD_STORE1),
137 new CLInsInfo(DSTORE_3, "dstore_3", 0, 3, -2, LOAD_STORE1),
138 new CLInsInfo(ASTORE_0, "astore_0", 0, 0, -1, LOAD_STORE1),
139 new CLInsInfo(ASTORE_1, "astore_1", 0, 1, -1, LOAD_STORE1),
140 new CLInsInfo(ASTORE_2, "astore_2", 0, 2, -1, LOAD_STORE1),
141 new CLInsInfo(ASTORE_3, "astore_3", 0, 3, -1, LOAD_STORE1),
142 new CLInsInfo(IASTORE, "iastore", 0, IRRELEVANT, -3, ARRAY2),
143 new CLInsInfo(LASTORE, "lastore", 0, IRRELEVANT, -4, ARRAY2),
144 new CLInsInfo(FASTORE, "fastore", 0, IRRELEVANT, -3, ARRAY2),
145 new CLInsInfo(DASTORE, "dastore", 0, IRRELEVANT, -4, ARRAY2),
146 new CLInsInfo(AASTORE, "aastore", 0, IRRELEVANT, -3, ARRAY2),
147 new CLInsInfo(BASTORE, "bastore", 0, IRRELEVANT, -3, ARRAY2),
148 new CLInsInfo(CASTORE, "castore", 0, IRRELEVANT, -3, ARRAY2),
149 new CLInsInfo(SASTORE, "sastore", 0, IRRELEVANT, -3, ARRAY2),
150 new CLInsInfo(POP, "pop", 0, IRRELEVANT, -1, STACK),
151 new CLInsInfo(POP2, "pop2", 0, IRRELEVANT, -2, STACK),
152 new CLInsInfo(DUP, "dup", 0, IRRELEVANT, 1, STACK),
153 new CLInsInfo(DUP_X1, "dup_x1", 0, IRRELEVANT, 1, STACK),
154 new CLInsInfo(DUP_X2, "dup_x2", 0, IRRELEVANT, 1, STACK),
155 new CLInsInfo(DUP2, "dup2", 0, IRRELEVANT, 2, STACK),
156 new CLInsInfo(DUP2_X1, "dup2_x1", 0, IRRELEVANT, 2, STACK),
157 new CLInsInfo(DUP2_X2, "dup2_x2", 0, IRRELEVANT, 2, STACK),
158 new CLInsInfo(SWAP, "swap", 0, IRRELEVANT, 0, STACK),
159 new CLInsInfo(IADD, "iadd", 0, IRRELEVANT, -1, ARITHMETIC1),
160 new CLInsInfo(LADD, "ladd", 0, IRRELEVANT, -2, ARITHMETIC1),
161 new CLInsInfo(FADD, "fadd", 0, IRRELEVANT, -1, ARITHMETIC1),
162 new CLInsInfo(DADD, "dadd", 0, IRRELEVANT, -2, ARITHMETIC1),
163 new CLInsInfo(ISUB, "isub", 0, IRRELEVANT, -1, ARITHMETIC1),
164 new CLInsInfo(LSUB, "lsub", 0, IRRELEVANT, -2, ARITHMETIC1),
165 new CLInsInfo(FSUB, "fsub", 0, IRRELEVANT, -1, ARITHMETIC1),
166 new CLInsInfo(DSUB, "dsub", 0, IRRELEVANT, -2, ARITHMETIC1),
167 new CLInsInfo(IMUL, "imul", 0, IRRELEVANT, -1, ARITHMETIC1),
168 new CLInsInfo(LMUL, "lmul", 0, IRRELEVANT, -2, ARITHMETIC1),
169 new CLInsInfo(FMUL, "fmul", 0, IRRELEVANT, -1, ARITHMETIC1),
170 new CLInsInfo(DMUL, "dmul", 0, IRRELEVANT, -2, ARITHMETIC1),
171 new CLInsInfo(IDIV, "idiv", 0, IRRELEVANT, -1, ARITHMETIC1),
172 new CLInsInfo(LDIV, "ldiv", 0, IRRELEVANT, -2, ARITHMETIC1),
173 new CLInsInfo(FDIV, "fdiv", 0, IRRELEVANT, -1, ARITHMETIC1),
174 new CLInsInfo(DDIV, "ddiv", 0, IRRELEVANT, -2, ARITHMETIC1),
175 new CLInsInfo(IREM, "irem", 0, IRRELEVANT, -1, ARITHMETIC1),
176 new CLInsInfo(LREM, "lrem", 0, IRRELEVANT, -2, ARITHMETIC1),
177 new CLInsInfo(FREM, "frem", 0, IRRELEVANT, -1, ARITHMETIC1),
178 new CLInsInfo(DREM, "drem", 0, IRRELEVANT, -2, ARITHMETIC1),
179 new CLInsInfo(INEG, "ineg", 0, IRRELEVANT, 0, ARITHMETIC1),
180 new CLInsInfo(LNEG, "lneg", 0, IRRELEVANT, 0, ARITHMETIC1),
181 new CLInsInfo(FNEG, "fneg", 0, IRRELEVANT, 0, ARITHMETIC1),
182 new CLInsInfo(DNEG, "dneg", 0, IRRELEVANT, 0, ARITHMETIC1),
183 new CLInsInfo(ISHL, "ishl", 0, IRRELEVANT, -1, BIT),
184 new CLInsInfo(LSHL, "lshl", 0, IRRELEVANT, -2, BIT),
185 new CLInsInfo(ISHR, "ishr", 0, IRRELEVANT, -1, BIT),
186 new CLInsInfo(LSHR, "lshr", 0, IRRELEVANT, -2, BIT),
187 new CLInsInfo(IUSHR, "iushr", 0, IRRELEVANT, -1, BIT),
188 new CLInsInfo(LUSHR, "lushr", 0, IRRELEVANT, -2, BIT),
189 new CLInsInfo(IAND, "iand", 0, IRRELEVANT, -1, BIT),
190 new CLInsInfo(LAND, "land", 0, IRRELEVANT, -2, BIT),
191 new CLInsInfo(IOR, "ior", 0, IRRELEVANT, -1, BIT),
192 new CLInsInfo(LOR, "lor", 0, IRRELEVANT, -2, BIT),
193 new CLInsInfo(IXOR, "ixor", 0, IRRELEVANT, -1, BIT),
194 new CLInsInfo(LXOR, "lxor", 0, IRRELEVANT, -2, BIT),
195 new CLInsInfo(IINC, "iinc", 2, DYNAMIC, 0, ARITHMETIC2),
196 new CLInsInfo(I2L, "i2l", 0, IRRELEVANT, 1, CONVERSION),
197 new CLInsInfo(I2F, "i2f", 0, IRRELEVANT, 0, CONVERSION),
198 new CLInsInfo(I2D, "i2d", 0, IRRELEVANT, 1, CONVERSION),
199 new CLInsInfo(L2I, "l2i", 0, IRRELEVANT, -1, CONVERSION),
200 new CLInsInfo(L2F, "l2f", 0, IRRELEVANT, -1, CONVERSION),
201 new CLInsInfo(L2D, "l2d", 0, IRRELEVANT, 0, CONVERSION),
202 new CLInsInfo(F2I, "f2i", 0, IRRELEVANT, 0, CONVERSION),
203 new CLInsInfo(F2L, "f2l", 0, IRRELEVANT, 1, CONVERSION),
204 new CLInsInfo(F2D, "f2d", 0, IRRELEVANT, 1, CONVERSION),
205 new CLInsInfo(D2I, "d2i", 0, IRRELEVANT, -1, CONVERSION),
206 new CLInsInfo(D2L, "d2l", 0, IRRELEVANT, 0, CONVERSION),
207 new CLInsInfo(D2F, "d2f", 0, IRRELEVANT, -1, CONVERSION),
208 new CLInsInfo(I2B, "i2b", 0, IRRELEVANT, 0, CONVERSION),
209 new CLInsInfo(I2C, "i2c", 0, IRRELEVANT, 0, CONVERSION),
210 new CLInsInfo(I2S, "i2s", 0, IRRELEVANT, 0, CONVERSION),
211 new CLInsInfo(LCMP, "lcmp", 0, IRRELEVANT, -3, COMPARISON),
212 new CLInsInfo(FCMPL, "fcmpl", 0, IRRELEVANT, -1, COMPARISON),
213 new CLInsInfo(FCMPG, "fcmpg", 0, IRRELEVANT, -1, COMPARISON),
214 new CLInsInfo(DCMPL, "dcmpl", 0, IRRELEVANT, -3, COMPARISON),
215 new CLInsInfo(DCMPG, "dcmpg", 0, IRRELEVANT, -3, COMPARISON),
216 new CLInsInfo(IFEQ, "ifeq", 2, IRRELEVANT, -1, FLOW_CONTROL1),
217 new CLInsInfo(IFNE, "ifne", 2, IRRELEVANT, -1, FLOW_CONTROL1),
218 new CLInsInfo(IFLT, "iflt", 2, IRRELEVANT, -1, FLOW_CONTROL1),
219 new CLInsInfo(IFGE, "ifge", 2, IRRELEVANT, -1, FLOW_CONTROL1),
220 new CLInsInfo(IFGT, "ifgt", 2, IRRELEVANT, -1, FLOW_CONTROL1),
221 new CLInsInfo(IFLE, "ifle", 2, IRRELEVANT, -1, FLOW_CONTROL1),
222 new CLInsInfo(IF_ICMPEQ, "if_icmpeq", 2, IRRELEVANT, -2,
223 FLOW_CONTROL1),
224 new CLInsInfo(IF_ICMPNE, "if_icmpne", 2, IRRELEVANT, -2,
225 FLOW_CONTROL1),
226 new CLInsInfo(IF_ICMPLT, "if_icmplt", 2, IRRELEVANT, -2,
227 FLOW_CONTROL1),
228 new CLInsInfo(IF_ICMPGE, "if_icmpge", 2, IRRELEVANT, -2,
229 FLOW_CONTROL1),
230 new CLInsInfo(IF_ICMPGT, "if_icmpgt", 2, IRRELEVANT, -2,
231 FLOW_CONTROL1),
232 new CLInsInfo(IF_ICMPLE, "if_icmple", 2, IRRELEVANT, -2,
233 FLOW_CONTROL1),
234 new CLInsInfo(IF_ACMPEQ, "if_acmpeq", 2, IRRELEVANT, -2,
235 FLOW_CONTROL1),
236 new CLInsInfo(IF_ACMPNE, "if_acmpne", 2, IRRELEVANT, -2,
237 FLOW_CONTROL1),
238 new CLInsInfo(GOTO, "goto", 2, IRRELEVANT, 0, FLOW_CONTROL1),
239 new CLInsInfo(JSR, "jsr", 2, IRRELEVANT, 1, FLOW_CONTROL1),
240 new CLInsInfo(RET, "ret", 1, IRRELEVANT, 0, FLOW_CONTROL2),
241 new CLInsInfo(TABLESWITCH, "tableswitch", DYNAMIC, IRRELEVANT, -1,
242 FLOW_CONTROL3),
243 new CLInsInfo(LOOKUPSWITCH, "lookupswitch", DYNAMIC, IRRELEVANT,
244 -1, FLOW_CONTROL4),
245 new CLInsInfo(IRETURN, "ireturn", 0, IRRELEVANT, EMPTY_STACK,
246 METHOD2),
247 new CLInsInfo(LRETURN, "lreturn", 0, IRRELEVANT, EMPTY_STACK,
248 METHOD2),
249 new CLInsInfo(FRETURN, "freturn", 0, IRRELEVANT, EMPTY_STACK,
250 METHOD2),
251 new CLInsInfo(DRETURN, "dreturn", 0, IRRELEVANT, EMPTY_STACK,
252 METHOD2),
253 new CLInsInfo(ARETURN, "areturn", 0, IRRELEVANT, EMPTY_STACK,
254 METHOD2),
255 new CLInsInfo(RETURN, "return", 0, IRRELEVANT, EMPTY_STACK, METHOD2),
256 new CLInsInfo(GETSTATIC, "getstatic", 2, IRRELEVANT, DYNAMIC, FIELD),
257 new CLInsInfo(PUTSTATIC, "putstatic", 2, IRRELEVANT, DYNAMIC, FIELD),
258 new CLInsInfo(GETFIELD, "getfield", 2, IRRELEVANT, DYNAMIC, FIELD),
259 new CLInsInfo(PUTFIELD, "putfield", 2, IRRELEVANT, DYNAMIC, FIELD),
260 new CLInsInfo(INVOKEVIRTUAL, "invokevirtual", 2, IRRELEVANT,
261 DYNAMIC, METHOD1),
262 new CLInsInfo(INVOKESPECIAL, "invokespecial", 2, IRRELEVANT,
263 DYNAMIC, METHOD1),
264 new CLInsInfo(INVOKESTATIC, "invokestatic", 2, IRRELEVANT, DYNAMIC,
265 METHOD1),
266 new CLInsInfo(INVOKEINTERFACE, "invokeinterface", 4, IRRELEVANT,
267 DYNAMIC, METHOD1),
268 new CLInsInfo(INVOKEDYNAMIC, "invokedynamic", 2, IRRELEVANT,
269 DYNAMIC, METHOD1),
270 new CLInsInfo(NEW, "new", 2, IRRELEVANT, 1, OBJECT),
271 new CLInsInfo(NEWARRAY, "newarray", 1, IRRELEVANT, 0, ARRAY1),
272 new CLInsInfo(ANEWARRAY, "anewarray", 2, IRRELEVANT, 0, ARRAY1),
273 new CLInsInfo(ARRAYLENGTH, "arraylength", 0, IRRELEVANT, 0, ARRAY2),
274 new CLInsInfo(ATHROW, "athrow", 0, IRRELEVANT, UNIT_SIZE_STACK,
275 MISC),
276 new CLInsInfo(CHECKCAST, "checkcast", 2, IRRELEVANT, 0, OBJECT),
277 new CLInsInfo(INSTANCEOF, "instanceof", 2, IRRELEVANT, 0, OBJECT),
278 new CLInsInfo(MONITORENTER, "monitorenter", 0, IRRELEVANT, -1, MISC),
279 new CLInsInfo(MONITOREXIT, "monitorexit", 0, IRRELEVANT, -1, MISC),
280 new CLInsInfo(WIDE, "wide", 3, IRRELEVANT, 0, LOAD_STORE1),
281 new CLInsInfo(MULTIANEWARRAY, "multianewarray", 3, IRRELEVANT, 0,
282 ARRAY3),
283 new CLInsInfo(IFNULL, "ifnull", 2, IRRELEVANT, -1, FLOW_CONTROL1),
284 new CLInsInfo(IFNONNULL, "ifnonnull", 2, IRRELEVANT, -1,
285 FLOW_CONTROL1),
286 new CLInsInfo(GOTO_W, "goto_w", 4, IRRELEVANT, 0, FLOW_CONTROL1),
287 new CLInsInfo(JSR_W, "jsr_w", 4, IRRELEVANT, 1, FLOW_CONTROL1) };
288
289
296
297 public static boolean isValid(int opcode) {
298 return NOP <= opcode && opcode <= JSR_W;
299 }
300
301
306
307 public int opcode() {
308 return opcode;
309 }
310
311
316
317 public String mnemonic() {
318 return mnemonic;
319 }
320
321
326
327 public int operandCount() {
328 return operandCount;
329 }
330
331
336
337 public int pc() {
338 return pc;
339 }
340
341
346
347 public int stackUnits() {
348 return stackUnits;
349 }
350
351
356
357 public int localVariableIndex() {
358 return localVariableIndex;
359 }
360
361
366
367 public abstract ArrayList<Integer> toBytes();
368
369
378
379 protected int byteAt(int i, int byteNum) {
380 int j = 0, mask = 0xFF;
381 switch (byteNum) {
382 case 1: j = i & mask;
384 break;
385 case 2:
386 j = (i >> 8) & mask;
387 break;
388 case 3:
389 j = (i >> 16) & mask;
390 break;
391 case 4: j = (i >> 24) & mask;
393 break;
394 }
395 return j;
396 }
397
398 }
399
400
403
404 class CLObjectInstruction extends CLInstruction {
405
406
410 private int index;
411
412
423
424 public CLObjectInstruction(int opcode, int pc, int index) {
425 super.opcode = opcode;
426 super.pc = pc;
427 mnemonic = instructionInfo[opcode].mnemonic;
428 operandCount = instructionInfo[opcode].operandCount;
429 stackUnits = instructionInfo[opcode].stackUnits;
430 localVariableIndex = instructionInfo[opcode].localVariableIndex;
431 this.index = index;
432 }
433
434
437
438 public ArrayList<Integer> toBytes() {
439 ArrayList<Integer> bytes = new ArrayList<Integer>();
440 bytes.add(opcode);
441 bytes.add(byteAt(index, 2));
442 bytes.add(byteAt(index, 1));
443 return bytes;
444 }
445
446 }
447
448
451
452 class CLFieldInstruction extends CLInstruction {
453
454
458 private int index;
459
460
474
475 public CLFieldInstruction(int opcode, int pc, int index, int stackUnits) {
476 super.opcode = opcode;
477 super.pc = pc;
478 mnemonic = instructionInfo[opcode].mnemonic;
479 operandCount = instructionInfo[opcode].operandCount;
480 super.stackUnits = stackUnits;
481 localVariableIndex = instructionInfo[opcode].localVariableIndex;
482 this.index = index;
483 }
484
485
488
489 public ArrayList<Integer> toBytes() {
490 ArrayList<Integer> bytes = new ArrayList<Integer>();
491 bytes.add(opcode);
492 bytes.add(byteAt(index, 2));
493 bytes.add(byteAt(index, 1));
494 return bytes;
495 }
496
497 }
498
499
502
503 class CLMethodInstruction extends CLInstruction {
504
505
509 private int index;
510
511
514 private int nArgs;
515
516
530
531 public CLMethodInstruction(int opcode, int pc, int index, int stackUnits) {
532 super.opcode = opcode;
533 super.pc = pc;
534 mnemonic = instructionInfo[opcode].mnemonic;
535 operandCount = instructionInfo[opcode].operandCount;
536 super.stackUnits = stackUnits;
537 localVariableIndex = instructionInfo[opcode].localVariableIndex;
538 this.index = index;
539 }
540
541
549
550 public CLMethodInstruction(int opcode, int pc) {
551 super.opcode = opcode;
552 super.pc = pc;
553 mnemonic = instructionInfo[opcode].mnemonic;
554 operandCount = instructionInfo[opcode].operandCount;
555 stackUnits = instructionInfo[opcode].stackUnits;
556 localVariableIndex = instructionInfo[opcode].localVariableIndex;
557 }
558
559
566
567 public void setArgumentCount(int nArgs) {
568 this.nArgs = nArgs;
569 }
570
571
574
575 public ArrayList<Integer> toBytes() {
576 ArrayList<Integer> bytes = new ArrayList<Integer>();
577 bytes.add(opcode);
578 if (instructionInfo[opcode].category == METHOD1) {
579 bytes.add(byteAt(index, 2));
580 bytes.add(byteAt(index, 1));
581
582 if (opcode == INVOKEINTERFACE) {
586 bytes.add(byteAt(nArgs, 1));
587 bytes.add(0);
588 }
589 }
590 return bytes;
591 }
592
593 }
594
595
598
599 class CLArrayInstruction extends CLInstruction {
600
601
606 private int type;
607
608
609 private int dim;
610
611
621
622 public CLArrayInstruction(int opcode, int pc, int type) {
623 super.opcode = opcode;
624 super.pc = pc;
625 mnemonic = instructionInfo[opcode].mnemonic;
626 operandCount = instructionInfo[opcode].operandCount;
627 stackUnits = instructionInfo[opcode].stackUnits;
628 localVariableIndex = instructionInfo[opcode].localVariableIndex;
629 this.type = type;
630 }
631
632
644
645 public CLArrayInstruction(int opcode, int pc, int type, int dim) {
646 super.opcode = opcode;
647 super.pc = pc;
648 mnemonic = instructionInfo[opcode].mnemonic;
649 operandCount = instructionInfo[opcode].operandCount;
650 stackUnits = instructionInfo[opcode].stackUnits;
651 localVariableIndex = instructionInfo[opcode].localVariableIndex;
652 this.type = type;
653 this.dim = dim;
654 }
655
656
664
665 public CLArrayInstruction(int opcode, int pc) {
666 super.opcode = opcode;
667 super.pc = pc;
668 mnemonic = instructionInfo[opcode].mnemonic;
669 operandCount = instructionInfo[opcode].operandCount;
670 stackUnits = instructionInfo[opcode].stackUnits;
671 localVariableIndex = instructionInfo[opcode].localVariableIndex;
672 }
673
674
677
678 public ArrayList<Integer> toBytes() {
679 ArrayList<Integer> bytes = new ArrayList<Integer>();
680 bytes.add(opcode);
681 switch (opcode) {
682 case NEWARRAY:
683 bytes.add(byteAt(type, 1));
684 break;
685 case ANEWARRAY:
686 bytes.add(byteAt(type, 2));
687 bytes.add(byteAt(type, 1));
688 break;
689 case MULTIANEWARRAY:
690 bytes.add(byteAt(type, 2));
691 bytes.add(byteAt(type, 1));
692 bytes.add(byteAt(dim, 1));
693 break;
694 }
695 return bytes;
696 }
697
698 }
699
700
703
704 class CLArithmeticInstruction extends CLInstruction {
705
706
710 private boolean isWidened;
711
712
713 private int constVal;
714
715
723
724 public CLArithmeticInstruction(int opcode, int pc) {
725 super.opcode = opcode;
726 super.pc = pc;
727 mnemonic = instructionInfo[opcode].mnemonic;
728 operandCount = instructionInfo[opcode].operandCount;
729 stackUnits = instructionInfo[opcode].stackUnits;
730 localVariableIndex = instructionInfo[opcode].localVariableIndex;
731 }
732
733
748
749 public CLArithmeticInstruction(int opcode, int pc, int localVariableIndex,
750 int constVal, boolean isWidened) {
751 super.opcode = opcode;
752 super.pc = pc;
753 super.localVariableIndex = localVariableIndex;
754 mnemonic = instructionInfo[opcode].mnemonic;
755 operandCount = instructionInfo[opcode].operandCount;
756 stackUnits = instructionInfo[opcode].stackUnits;
757 this.constVal = constVal;
758 this.isWidened = isWidened;
759 }
760
761
764
765 public ArrayList<Integer> toBytes() {
766 ArrayList<Integer> bytes = new ArrayList<Integer>();
767 bytes.add(opcode);
768 if (opcode == IINC) {
769 if (isWidened) {
770 bytes.add(byteAt(localVariableIndex, 2));
771 bytes.add(byteAt(localVariableIndex, 1));
772 bytes.add(byteAt(constVal, 2));
773 bytes.add(byteAt(constVal, 1));
774 } else {
775 bytes.add(byteAt(localVariableIndex, 1));
776 bytes.add(byteAt(constVal, 1));
777 }
778 }
779 return bytes;
780 }
781
782 }
783
784
787
788 class CLBitInstruction extends CLInstruction {
789
790
798
799 public CLBitInstruction(int opcode, int pc) {
800 super.opcode = opcode;
801 super.pc = pc;
802 mnemonic = instructionInfo[opcode].mnemonic;
803 operandCount = instructionInfo[opcode].operandCount;
804 stackUnits = instructionInfo[opcode].stackUnits;
805 localVariableIndex = instructionInfo[opcode].localVariableIndex;
806 }
807
808
811
812 public ArrayList<Integer> toBytes() {
813 ArrayList<Integer> bytes = new ArrayList<Integer>();
814 bytes.add(opcode);
815 return bytes;
816 }
817
818 }
819
820
823
824 class CLComparisonInstruction extends CLInstruction {
825
826
834
835 public CLComparisonInstruction(int opcode, int pc) {
836 super.opcode = opcode;
837 super.pc = pc;
838 mnemonic = instructionInfo[opcode].mnemonic;
839 operandCount = instructionInfo[opcode].operandCount;
840 stackUnits = instructionInfo[opcode].stackUnits;
841 localVariableIndex = instructionInfo[opcode].localVariableIndex;
842 }
843
844
847
848 public ArrayList<Integer> toBytes() {
849 ArrayList<Integer> bytes = new ArrayList<Integer>();
850 bytes.add(opcode);
851 return bytes;
852 }
853
854 }
855
856
859
860 class CLConversionInstruction extends CLInstruction {
861
862
870
871 public CLConversionInstruction(int opcode, int pc) {
872 super.opcode = opcode;
873 super.pc = pc;
874 mnemonic = instructionInfo[opcode].mnemonic;
875 operandCount = instructionInfo[opcode].operandCount;
876 stackUnits = instructionInfo[opcode].stackUnits;
877 localVariableIndex = instructionInfo[opcode].localVariableIndex;
878 }
879
880
883
884 public ArrayList<Integer> toBytes() {
885 ArrayList<Integer> bytes = new ArrayList<Integer>();
886 bytes.add(opcode);
887 return bytes;
888 }
889
890 }
891
892
896
897 class CLFlowControlInstruction extends CLInstruction {
898
899
903 private String jumpToLabel;
904
905
906 private int jumpToOffset;
907
908
912 private int index;
913
914
918 private boolean isWidened;
919
920
924 private int pad;
925
926
930 private String defaultLabel;
931
932
933 private int defaultOffset;
934
935
938 private int numPairs;
939
940
941 private TreeMap<Integer, String> matchLabelPairs;
942
943
947 private TreeMap<Integer, Integer> matchOffsetPairs;
948
949
950 private int low;
951
952
953 private int high;
954
955
959 private ArrayList<String> labels;
960
961
965 private ArrayList<Integer> offsets;
966
967
978
979 public CLFlowControlInstruction(int opcode, int pc, String jumpToLabel) {
980 super.opcode = opcode;
981 super.pc = pc;
982 mnemonic = instructionInfo[opcode].mnemonic;
983 operandCount = instructionInfo[opcode].operandCount;
984 stackUnits = instructionInfo[opcode].stackUnits;
985 localVariableIndex = instructionInfo[opcode].localVariableIndex;
986 this.jumpToLabel = jumpToLabel;
987 }
988
989
1000
1001 public CLFlowControlInstruction(int pc, int index, boolean isWidened) {
1002 super.opcode = RET;
1003 super.pc = pc;
1004 mnemonic = instructionInfo[opcode].mnemonic;
1005 operandCount = instructionInfo[opcode].operandCount;
1006 stackUnits = instructionInfo[opcode].stackUnits;
1007 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1008 this.index = index;
1009 this.isWidened = isWidened;
1010 }
1011
1012
1029
1030 public CLFlowControlInstruction(int opcode, int pc, String defaultLabel,
1031 int low, int high, ArrayList<String> labels) {
1032 super.opcode = opcode;
1033 super.pc = pc;
1034 mnemonic = instructionInfo[opcode].mnemonic;
1035 stackUnits = instructionInfo[opcode].stackUnits;
1036 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1037 this.defaultLabel = defaultLabel;
1038 this.low = low;
1039 this.high = high;
1040 this.labels = labels;
1041 pad = 4 - ((pc + 1) % 4);
1042 operandCount = pad + 12 + 4 * labels.size();
1043 }
1044
1045
1059
1060 public CLFlowControlInstruction(int opcode, int pc, String defaultLabel,
1061 int numPairs, TreeMap<Integer, String> matchLabelPairs) {
1062 super.opcode = opcode;
1063 super.pc = pc;
1064 mnemonic = instructionInfo[opcode].mnemonic;
1065 stackUnits = instructionInfo[opcode].stackUnits;
1066 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1067 this.defaultLabel = defaultLabel;
1068 this.numPairs = numPairs;
1069 this.matchLabelPairs = matchLabelPairs;
1070 pad = 4 - ((pc + 1) % 4);
1071 operandCount = pad + 8 + 8 * numPairs;
1072 }
1073
1074
1083
1084 public boolean resolveLabels(Hashtable<String, Integer> labelToPC) {
1085 boolean allLabelsResolved = true;
1086 if (instructionInfo[opcode].category == FLOW_CONTROL1) {
1087 if (labelToPC.containsKey(jumpToLabel)) {
1088 jumpToOffset = labelToPC.get(jumpToLabel) - pc;
1089 } else {
1090 jumpToOffset = operandCount;
1091 allLabelsResolved = false;
1092 }
1093 } else if (opcode == LOOKUPSWITCH) {
1094 if (labelToPC.containsKey(defaultLabel)) {
1095 defaultOffset = labelToPC.get(defaultLabel) - pc;
1096 } else {
1097 defaultOffset = operandCount;
1098 allLabelsResolved = false;
1099 }
1100 matchOffsetPairs = new TreeMap<Integer, Integer>();
1101 Set<Entry<Integer, String>> matches = matchLabelPairs.entrySet();
1102 Iterator<Entry<Integer, String>> iter = matches.iterator();
1103 while (iter.hasNext()) {
1104 Entry<Integer, String> entry = iter.next();
1105 int match = entry.getKey();
1106 String label = entry.getValue();
1107 if (labelToPC.containsKey(label)) {
1108 matchOffsetPairs.put(match, labelToPC.get(label) - pc);
1109 } else {
1110 matchOffsetPairs.put(match, operandCount);
1111 allLabelsResolved = false;
1112 }
1113 }
1114 } else if (opcode == TABLESWITCH) {
1115 if (labelToPC.containsKey(defaultLabel)) {
1116 defaultOffset = labelToPC.get(defaultLabel) - pc;
1117 } else {
1118 defaultOffset = operandCount;
1119 allLabelsResolved = false;
1120 }
1121 offsets = new ArrayList<Integer>();
1122 for (int i = 0; i < labels.size(); i++) {
1123 if (labelToPC.containsKey(labels.get(i))) {
1124 offsets.add(labelToPC.get(labels.get(i)) - pc);
1125 } else {
1126 offsets.add(operandCount);
1127 allLabelsResolved = false;
1128 }
1129 }
1130 }
1131 return allLabelsResolved;
1132 }
1133
1134
1139
1140 public int jumpToOffset() {
1141 return jumpToOffset;
1142 }
1143
1144
1147
1148 public ArrayList<Integer> toBytes() {
1149 ArrayList<Integer> bytes = new ArrayList<Integer>();
1150 bytes.add(opcode);
1151 switch (opcode) {
1152 case RET:
1153 if (isWidened) {
1154 bytes.add(byteAt(index, 2));
1155 bytes.add(byteAt(index, 1));
1156 } else {
1157 bytes.add(byteAt(index, 1));
1158 }
1159 break;
1160 case TABLESWITCH:
1161 for (int i = 0; i < pad; i++) {
1162 bytes.add(0);
1163 }
1164 bytes.add(byteAt(defaultOffset, 4));
1165 bytes.add(byteAt(defaultOffset, 3));
1166 bytes.add(byteAt(defaultOffset, 2));
1167 bytes.add(byteAt(defaultOffset, 1));
1168 bytes.add(byteAt(low, 4));
1169 bytes.add(byteAt(low, 3));
1170 bytes.add(byteAt(low, 2));
1171 bytes.add(byteAt(low, 1));
1172 bytes.add(byteAt(high, 4));
1173 bytes.add(byteAt(high, 3));
1174 bytes.add(byteAt(high, 2));
1175 bytes.add(byteAt(high, 1));
1176 for (int i = 0; i < offsets.size(); i++) {
1177 int jumpOffset = offsets.get(i);
1178 bytes.add(byteAt(jumpOffset, 4));
1179 bytes.add(byteAt(jumpOffset, 3));
1180 bytes.add(byteAt(jumpOffset, 2));
1181 bytes.add(byteAt(jumpOffset, 1));
1182 }
1183 break;
1184 case LOOKUPSWITCH:
1185 for (int i = 0; i < pad; i++) {
1186 bytes.add(0);
1187 }
1188 bytes.add(byteAt(defaultOffset, 4));
1189 bytes.add(byteAt(defaultOffset, 3));
1190 bytes.add(byteAt(defaultOffset, 2));
1191 bytes.add(byteAt(defaultOffset, 1));
1192 bytes.add(byteAt(numPairs, 4));
1193 bytes.add(byteAt(numPairs, 3));
1194 bytes.add(byteAt(numPairs, 2));
1195 bytes.add(byteAt(numPairs, 1));
1196 Set<Entry<Integer, Integer>> matches = matchOffsetPairs.entrySet();
1197 Iterator<Entry<Integer, Integer>> iter = matches.iterator();
1198 while (iter.hasNext()) {
1199 Entry<Integer, Integer> entry = iter.next();
1200 int match = entry.getKey();
1201 int offset = entry.getValue();
1202 bytes.add(byteAt(match, 4));
1203 bytes.add(byteAt(match, 3));
1204 bytes.add(byteAt(match, 2));
1205 bytes.add(byteAt(match, 1));
1206 bytes.add(byteAt(offset, 4));
1207 bytes.add(byteAt(offset, 3));
1208 bytes.add(byteAt(offset, 2));
1209 bytes.add(byteAt(offset, 1));
1210 }
1211 break;
1212 case GOTO_W:
1213 case JSR_W:
1214 bytes.add(byteAt(jumpToOffset, 4));
1215 bytes.add(byteAt(jumpToOffset, 3));
1216 bytes.add(byteAt(jumpToOffset, 2));
1217 bytes.add(byteAt(jumpToOffset, 1));
1218 break;
1219 default:
1220 bytes.add(byteAt(jumpToOffset, 2));
1221 bytes.add(byteAt(jumpToOffset, 1));
1222 }
1223 return bytes;
1224 }
1225
1226}
1227
1228
1232
1233class CLLoadStoreInstruction extends CLInstruction {
1234
1235
1240 private boolean isWidened;
1241
1242
1246 private int constVal;
1247
1248
1256
1257 public CLLoadStoreInstruction(int opcode, int pc) {
1258 super.opcode = opcode;
1259 super.pc = pc;
1260 mnemonic = instructionInfo[opcode].mnemonic;
1261 operandCount = instructionInfo[opcode].operandCount;
1262 stackUnits = instructionInfo[opcode].stackUnits;
1263 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1264 }
1265
1266
1279
1280 public CLLoadStoreInstruction(int opcode, int pc, int localVariableIndex,
1281 boolean isWidened) {
1282 super.opcode = opcode;
1283 super.pc = pc;
1284 mnemonic = instructionInfo[opcode].mnemonic;
1285 operandCount = instructionInfo[opcode].operandCount;
1286 stackUnits = instructionInfo[opcode].stackUnits;
1287 super.localVariableIndex = localVariableIndex;
1288 this.isWidened = isWidened;
1289 }
1290
1291
1303
1304 public CLLoadStoreInstruction(int opcode, int pc, int constVal) {
1305 super.opcode = opcode;
1306 super.pc = pc;
1307 mnemonic = instructionInfo[opcode].mnemonic;
1308 operandCount = instructionInfo[opcode].operandCount;
1309 stackUnits = instructionInfo[opcode].stackUnits;
1310 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1311 this.constVal = constVal;
1312 }
1313
1314
1317
1318 public ArrayList<Integer> toBytes() {
1319 ArrayList<Integer> bytes = new ArrayList<Integer>();
1320 bytes.add(opcode);
1321 if (instructionInfo[opcode].operandCount > 0) {
1322 if (localVariableIndex != IRRELEVANT) {
1323 if (isWidened) {
1324 bytes.add(byteAt(localVariableIndex, 2));
1325 }
1326 bytes.add(byteAt(localVariableIndex, 1));
1327 } else {
1328 switch (opcode) {
1329 case BIPUSH:
1330 case LDC:
1331 bytes.add(byteAt(constVal, 1));
1332 break;
1333 case SIPUSH:
1334 case LDC_W:
1335 case LDC2_W:
1336 bytes.add(byteAt(constVal, 2));
1337 bytes.add(byteAt(constVal, 1));
1338 }
1339 }
1340 }
1341 return bytes;
1342 }
1343
1344}
1345
1346
1349
1350class CLStackInstruction extends CLInstruction {
1351
1352
1360
1361 public CLStackInstruction(int opcode, int pc) {
1362 super.opcode = opcode;
1363 super.pc = pc;
1364 mnemonic = instructionInfo[opcode].mnemonic;
1365 operandCount = instructionInfo[opcode].operandCount;
1366 stackUnits = instructionInfo[opcode].stackUnits;
1367 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1368 }
1369
1370
1373
1374 public ArrayList<Integer> toBytes() {
1375 ArrayList<Integer> bytes = new ArrayList<Integer>();
1376 bytes.add(opcode);
1377 return bytes;
1378 }
1379
1380}
1381
1382
1385
1386class CLMiscInstruction extends CLInstruction {
1387
1388
1396
1397 public CLMiscInstruction(int opcode, int pc) {
1398 super.opcode = opcode;
1399 super.pc = pc;
1400 mnemonic = instructionInfo[opcode].mnemonic;
1401 operandCount = instructionInfo[opcode].operandCount;
1402 stackUnits = instructionInfo[opcode].stackUnits;
1403 localVariableIndex = instructionInfo[opcode].localVariableIndex;
1404 }
1405
1406
1409
1410 public ArrayList<Integer> toBytes() {
1411 ArrayList<Integer> bytes = new ArrayList<Integer>();
1412 bytes.add(opcode);
1413 return bytes;
1414 }
1415
1416}
1417
1418
1421
1422class CLInsInfo {
1423
1424
1425 public int opcode;
1426
1427
1428 public String mnemonic;
1429
1430
1431 public int operandCount;
1432
1433
1437 public int stackUnits;
1438
1439
1443 public int localVariableIndex;
1444
1445
1446 public Category category;
1447
1448
1465
1466 public CLInsInfo(int opcode, String mnemonic, int operandCount,
1467 int localVariableIndex, int stackUnits, Category category) {
1468 this.opcode = opcode;
1469 this.mnemonic = mnemonic;
1470 this.operandCount = operandCount;
1471 this.localVariableIndex = localVariableIndex;
1472 this.stackUnits = stackUnits;
1473 this.category = category;
1474 }
1475
1476}
1477