blob: ae4d7bdd531617aa54de4928ac170a26a465f988 [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 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 */
Andy McFadden3a1aedb2009-05-07 13:30:23 -070016
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080017/*
18 * Dalvik instruction utility functions.
19 */
20#include "InstrUtils.h"
21
22#include <stdlib.h>
23
24
25/*
26 * Generate a table that holds the width of all instructions.
27 *
28 * Standard instructions have positive values, optimizer instructions
29 * have negative values, unimplemented instructions have a width of zero.
30 *
31 * I'm doing it with a giant switch statement because it's easier to
32 * maintain and update than a static table with 256 unadorned integers,
33 * and if we're missing a case gcc emits a "warning: enumeration value not
34 * handled" message.
35 *
36 * (To save space in the binary we could generate a static table with a
37 * command-line utility.)
Andy McFadden861b3382010-03-05 15:58:31 -080038 *
39 * TODO: it doesn't look like we're using the negative values anymore.
40 * Consider switching to only positive values.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080041 */
42InstructionWidth* dexCreateInstrWidthTable(void)
43{
David 'Digit' Turnerec628b52009-09-20 11:58:16 -070044#ifdef __ARM_ARCH_7A__
45 /* hack to work around mysterious problem on emulator */
46 LOGD("creating instr width table\n");
47#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080048 InstructionWidth* instrWidth;
49 int i;
50
51 instrWidth = malloc(sizeof(InstructionWidth) * kNumDalvikInstructions);
52 if (instrWidth == NULL)
53 return NULL;
54
55 for (i = 0; i < kNumDalvikInstructions; i++) {
56 OpCode opc = (OpCode) i;
57 int width = 0;
58
59 switch (opc) {
Andy McFadden3a1aedb2009-05-07 13:30:23 -070060 case OP_NOP: /* note data for e.g. switch-* encoded "inside" a NOP */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080061 case OP_MOVE:
62 case OP_MOVE_WIDE:
63 case OP_MOVE_OBJECT:
64 case OP_MOVE_RESULT:
65 case OP_MOVE_RESULT_WIDE:
66 case OP_MOVE_RESULT_OBJECT:
67 case OP_MOVE_EXCEPTION:
68 case OP_RETURN_VOID:
69 case OP_RETURN:
70 case OP_RETURN_WIDE:
71 case OP_RETURN_OBJECT:
72 case OP_CONST_4:
73 case OP_MONITOR_ENTER:
74 case OP_MONITOR_EXIT:
75 case OP_ARRAY_LENGTH:
76 case OP_THROW:
77 case OP_GOTO:
78 case OP_NEG_INT:
79 case OP_NOT_INT:
80 case OP_NEG_LONG:
81 case OP_NOT_LONG:
82 case OP_NEG_FLOAT:
83 case OP_NEG_DOUBLE:
84 case OP_INT_TO_LONG:
85 case OP_INT_TO_FLOAT:
86 case OP_INT_TO_DOUBLE:
87 case OP_LONG_TO_INT:
88 case OP_LONG_TO_FLOAT:
89 case OP_LONG_TO_DOUBLE:
90 case OP_FLOAT_TO_INT:
91 case OP_FLOAT_TO_LONG:
92 case OP_FLOAT_TO_DOUBLE:
93 case OP_DOUBLE_TO_INT:
94 case OP_DOUBLE_TO_LONG:
95 case OP_DOUBLE_TO_FLOAT:
96 case OP_INT_TO_BYTE:
97 case OP_INT_TO_CHAR:
98 case OP_INT_TO_SHORT:
99 case OP_ADD_INT_2ADDR:
100 case OP_SUB_INT_2ADDR:
101 case OP_MUL_INT_2ADDR:
102 case OP_DIV_INT_2ADDR:
103 case OP_REM_INT_2ADDR:
104 case OP_AND_INT_2ADDR:
105 case OP_OR_INT_2ADDR:
106 case OP_XOR_INT_2ADDR:
107 case OP_SHL_INT_2ADDR:
108 case OP_SHR_INT_2ADDR:
109 case OP_USHR_INT_2ADDR:
110 case OP_ADD_LONG_2ADDR:
111 case OP_SUB_LONG_2ADDR:
112 case OP_MUL_LONG_2ADDR:
113 case OP_DIV_LONG_2ADDR:
114 case OP_REM_LONG_2ADDR:
115 case OP_AND_LONG_2ADDR:
116 case OP_OR_LONG_2ADDR:
117 case OP_XOR_LONG_2ADDR:
118 case OP_SHL_LONG_2ADDR:
119 case OP_SHR_LONG_2ADDR:
120 case OP_USHR_LONG_2ADDR:
121 case OP_ADD_FLOAT_2ADDR:
122 case OP_SUB_FLOAT_2ADDR:
123 case OP_MUL_FLOAT_2ADDR:
124 case OP_DIV_FLOAT_2ADDR:
125 case OP_REM_FLOAT_2ADDR:
126 case OP_ADD_DOUBLE_2ADDR:
127 case OP_SUB_DOUBLE_2ADDR:
128 case OP_MUL_DOUBLE_2ADDR:
129 case OP_DIV_DOUBLE_2ADDR:
130 case OP_REM_DOUBLE_2ADDR:
131 width = 1;
132 break;
133
134 case OP_MOVE_FROM16:
135 case OP_MOVE_WIDE_FROM16:
136 case OP_MOVE_OBJECT_FROM16:
137 case OP_CONST_16:
138 case OP_CONST_HIGH16:
139 case OP_CONST_WIDE_16:
140 case OP_CONST_WIDE_HIGH16:
141 case OP_CONST_STRING:
142 case OP_CONST_CLASS:
143 case OP_CHECK_CAST:
144 case OP_INSTANCE_OF:
145 case OP_NEW_INSTANCE:
146 case OP_NEW_ARRAY:
147 case OP_CMPL_FLOAT:
148 case OP_CMPG_FLOAT:
149 case OP_CMPL_DOUBLE:
150 case OP_CMPG_DOUBLE:
151 case OP_CMP_LONG:
152 case OP_GOTO_16:
153 case OP_IF_EQ:
154 case OP_IF_NE:
155 case OP_IF_LT:
156 case OP_IF_GE:
157 case OP_IF_GT:
158 case OP_IF_LE:
159 case OP_IF_EQZ:
160 case OP_IF_NEZ:
161 case OP_IF_LTZ:
162 case OP_IF_GEZ:
163 case OP_IF_GTZ:
164 case OP_IF_LEZ:
165 case OP_AGET:
166 case OP_AGET_WIDE:
167 case OP_AGET_OBJECT:
168 case OP_AGET_BOOLEAN:
169 case OP_AGET_BYTE:
170 case OP_AGET_CHAR:
171 case OP_AGET_SHORT:
172 case OP_APUT:
173 case OP_APUT_WIDE:
174 case OP_APUT_OBJECT:
175 case OP_APUT_BOOLEAN:
176 case OP_APUT_BYTE:
177 case OP_APUT_CHAR:
178 case OP_APUT_SHORT:
179 case OP_IGET:
180 case OP_IGET_WIDE:
181 case OP_IGET_OBJECT:
182 case OP_IGET_BOOLEAN:
183 case OP_IGET_BYTE:
184 case OP_IGET_CHAR:
185 case OP_IGET_SHORT:
186 case OP_IPUT:
187 case OP_IPUT_WIDE:
188 case OP_IPUT_OBJECT:
189 case OP_IPUT_BOOLEAN:
190 case OP_IPUT_BYTE:
191 case OP_IPUT_CHAR:
192 case OP_IPUT_SHORT:
193 case OP_SGET:
194 case OP_SGET_WIDE:
195 case OP_SGET_OBJECT:
196 case OP_SGET_BOOLEAN:
197 case OP_SGET_BYTE:
198 case OP_SGET_CHAR:
199 case OP_SGET_SHORT:
200 case OP_SPUT:
201 case OP_SPUT_WIDE:
202 case OP_SPUT_OBJECT:
203 case OP_SPUT_BOOLEAN:
204 case OP_SPUT_BYTE:
205 case OP_SPUT_CHAR:
206 case OP_SPUT_SHORT:
207 case OP_ADD_INT:
208 case OP_SUB_INT:
209 case OP_MUL_INT:
210 case OP_DIV_INT:
211 case OP_REM_INT:
212 case OP_AND_INT:
213 case OP_OR_INT:
214 case OP_XOR_INT:
215 case OP_SHL_INT:
216 case OP_SHR_INT:
217 case OP_USHR_INT:
218 case OP_ADD_LONG:
219 case OP_SUB_LONG:
220 case OP_MUL_LONG:
221 case OP_DIV_LONG:
222 case OP_REM_LONG:
223 case OP_AND_LONG:
224 case OP_OR_LONG:
225 case OP_XOR_LONG:
226 case OP_SHL_LONG:
227 case OP_SHR_LONG:
228 case OP_USHR_LONG:
229 case OP_ADD_FLOAT:
230 case OP_SUB_FLOAT:
231 case OP_MUL_FLOAT:
232 case OP_DIV_FLOAT:
233 case OP_REM_FLOAT:
234 case OP_ADD_DOUBLE:
235 case OP_SUB_DOUBLE:
236 case OP_MUL_DOUBLE:
237 case OP_DIV_DOUBLE:
238 case OP_REM_DOUBLE:
239 case OP_ADD_INT_LIT16:
240 case OP_RSUB_INT:
241 case OP_MUL_INT_LIT16:
242 case OP_DIV_INT_LIT16:
243 case OP_REM_INT_LIT16:
244 case OP_AND_INT_LIT16:
245 case OP_OR_INT_LIT16:
246 case OP_XOR_INT_LIT16:
247 case OP_ADD_INT_LIT8:
248 case OP_RSUB_INT_LIT8:
249 case OP_MUL_INT_LIT8:
250 case OP_DIV_INT_LIT8:
251 case OP_REM_INT_LIT8:
252 case OP_AND_INT_LIT8:
253 case OP_OR_INT_LIT8:
254 case OP_XOR_INT_LIT8:
255 case OP_SHL_INT_LIT8:
256 case OP_SHR_INT_LIT8:
257 case OP_USHR_INT_LIT8:
258 width = 2;
259 break;
260
261 case OP_MOVE_16:
262 case OP_MOVE_WIDE_16:
263 case OP_MOVE_OBJECT_16:
264 case OP_CONST:
265 case OP_CONST_WIDE_32:
266 case OP_CONST_STRING_JUMBO:
267 case OP_GOTO_32:
268 case OP_FILLED_NEW_ARRAY:
269 case OP_FILLED_NEW_ARRAY_RANGE:
270 case OP_FILL_ARRAY_DATA:
271 case OP_PACKED_SWITCH:
272 case OP_SPARSE_SWITCH:
273 case OP_INVOKE_VIRTUAL:
274 case OP_INVOKE_SUPER:
275 case OP_INVOKE_DIRECT:
276 case OP_INVOKE_STATIC:
277 case OP_INVOKE_INTERFACE:
278 case OP_INVOKE_VIRTUAL_RANGE:
279 case OP_INVOKE_SUPER_RANGE:
280 case OP_INVOKE_DIRECT_RANGE:
281 case OP_INVOKE_STATIC_RANGE:
282 case OP_INVOKE_INTERFACE_RANGE:
283 width = 3;
284 break;
285
286 case OP_CONST_WIDE:
287 width = 5;
288 break;
289
290 /*
291 * Optimized instructions. We return negative size values for these
292 * to distinguish them.
293 */
Andy McFadden291758c2010-09-10 08:04:52 -0700294 case OP_RETURN_VOID_BARRIER:
295 width = -1;
296 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800297 case OP_IGET_QUICK:
298 case OP_IGET_WIDE_QUICK:
299 case OP_IGET_OBJECT_QUICK:
300 case OP_IPUT_QUICK:
301 case OP_IPUT_WIDE_QUICK:
302 case OP_IPUT_OBJECT_QUICK:
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700303 case OP_IGET_VOLATILE:
304 case OP_IPUT_VOLATILE:
305 case OP_SGET_VOLATILE:
306 case OP_SPUT_VOLATILE:
307 case OP_IGET_OBJECT_VOLATILE:
308 case OP_IPUT_OBJECT_VOLATILE:
309 case OP_SGET_OBJECT_VOLATILE:
310 case OP_SPUT_OBJECT_VOLATILE:
Andy McFadden53878242010-03-05 07:24:27 -0800311 case OP_IGET_WIDE_VOLATILE:
312 case OP_IPUT_WIDE_VOLATILE:
313 case OP_SGET_WIDE_VOLATILE:
314 case OP_SPUT_WIDE_VOLATILE:
Andy McFadden3a1aedb2009-05-07 13:30:23 -0700315 case OP_THROW_VERIFICATION_ERROR:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800316 width = -2;
317 break;
318 case OP_INVOKE_VIRTUAL_QUICK:
319 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
320 case OP_INVOKE_SUPER_QUICK:
321 case OP_INVOKE_SUPER_QUICK_RANGE:
322 case OP_EXECUTE_INLINE:
Andy McFaddenb0a05412009-11-19 10:23:41 -0800323 case OP_EXECUTE_INLINE_RANGE:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800324 case OP_INVOKE_DIRECT_EMPTY:
325 width = -3;
326 break;
327
Andy McFadden96516932009-10-28 17:39:02 -0700328 /* these should never appear when scanning bytecode */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800329 case OP_UNUSED_3E:
330 case OP_UNUSED_3F:
331 case OP_UNUSED_40:
332 case OP_UNUSED_41:
333 case OP_UNUSED_42:
334 case OP_UNUSED_43:
335 case OP_UNUSED_73:
336 case OP_UNUSED_79:
337 case OP_UNUSED_7A:
Andy McFadden96516932009-10-28 17:39:02 -0700338 case OP_BREAKPOINT:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800339 case OP_UNUSED_FF:
340 assert(width == 0);
341 break;
342
343 /*
344 * DO NOT add a "default" clause here. Without it the compiler will
345 * complain if an instruction is missing (which is desirable).
346 */
347 }
348
349 instrWidth[opc] = width;
350 }
351
352 return instrWidth;
353}
354
355/*
356 * Generate a table that holds instruction flags.
357 */
358InstructionFlags* dexCreateInstrFlagsTable(void)
359{
360 InstructionFlags* instrFlags;
361 int i;
362
363 instrFlags = malloc(sizeof(InstructionFlags) * kNumDalvikInstructions);
364 if (instrFlags == NULL)
365 return NULL;
366
367 for (i = 0; i < kNumDalvikInstructions; i++) {
368 OpCode opc = (OpCode) i;
369 InstructionFlags flags = 0;
370
371 switch (opc) {
372 /* these don't affect the PC and can't cause an exception */
373 case OP_NOP:
374 case OP_MOVE:
375 case OP_MOVE_FROM16:
376 case OP_MOVE_16:
377 case OP_MOVE_WIDE:
378 case OP_MOVE_WIDE_FROM16:
379 case OP_MOVE_WIDE_16:
380 case OP_MOVE_OBJECT:
381 case OP_MOVE_OBJECT_FROM16:
382 case OP_MOVE_OBJECT_16:
383 case OP_MOVE_RESULT:
384 case OP_MOVE_RESULT_WIDE:
385 case OP_MOVE_RESULT_OBJECT:
386 case OP_MOVE_EXCEPTION:
387 case OP_CONST_4:
388 case OP_CONST_16:
389 case OP_CONST:
390 case OP_CONST_HIGH16:
391 case OP_CONST_WIDE_16:
392 case OP_CONST_WIDE_32:
393 case OP_CONST_WIDE:
394 case OP_CONST_WIDE_HIGH16:
395 case OP_FILL_ARRAY_DATA:
396 case OP_CMPL_FLOAT:
397 case OP_CMPG_FLOAT:
398 case OP_CMPL_DOUBLE:
399 case OP_CMPG_DOUBLE:
400 case OP_CMP_LONG:
401 case OP_NEG_INT:
402 case OP_NOT_INT:
403 case OP_NEG_LONG:
404 case OP_NOT_LONG:
405 case OP_NEG_FLOAT:
406 case OP_NEG_DOUBLE:
407 case OP_INT_TO_LONG:
408 case OP_INT_TO_FLOAT:
409 case OP_INT_TO_DOUBLE:
410 case OP_LONG_TO_INT:
411 case OP_LONG_TO_FLOAT:
412 case OP_LONG_TO_DOUBLE:
413 case OP_FLOAT_TO_INT:
414 case OP_FLOAT_TO_LONG:
415 case OP_FLOAT_TO_DOUBLE:
416 case OP_DOUBLE_TO_INT:
417 case OP_DOUBLE_TO_LONG:
418 case OP_DOUBLE_TO_FLOAT:
419 case OP_INT_TO_BYTE:
420 case OP_INT_TO_CHAR:
421 case OP_INT_TO_SHORT:
422 case OP_ADD_INT:
423 case OP_SUB_INT:
424 case OP_MUL_INT:
425 case OP_AND_INT:
426 case OP_OR_INT:
427 case OP_XOR_INT:
428 case OP_SHL_INT:
429 case OP_SHR_INT:
430 case OP_USHR_INT:
431 case OP_ADD_LONG:
432 case OP_SUB_LONG:
433 case OP_MUL_LONG:
434 case OP_AND_LONG:
435 case OP_OR_LONG:
436 case OP_XOR_LONG:
437 case OP_SHL_LONG:
438 case OP_SHR_LONG:
439 case OP_USHR_LONG:
440 case OP_ADD_FLOAT:
441 case OP_SUB_FLOAT:
442 case OP_MUL_FLOAT:
443 case OP_DIV_FLOAT:
444 case OP_REM_FLOAT:
445 case OP_ADD_DOUBLE:
446 case OP_SUB_DOUBLE:
447 case OP_MUL_DOUBLE:
448 case OP_DIV_DOUBLE: // div by zero just returns NaN
449 case OP_REM_DOUBLE:
450 case OP_ADD_INT_2ADDR:
451 case OP_SUB_INT_2ADDR:
452 case OP_MUL_INT_2ADDR:
453 case OP_AND_INT_2ADDR:
454 case OP_OR_INT_2ADDR:
455 case OP_XOR_INT_2ADDR:
456 case OP_SHL_INT_2ADDR:
457 case OP_SHR_INT_2ADDR:
458 case OP_USHR_INT_2ADDR:
459 case OP_ADD_LONG_2ADDR:
460 case OP_SUB_LONG_2ADDR:
461 case OP_MUL_LONG_2ADDR:
462 case OP_AND_LONG_2ADDR:
463 case OP_OR_LONG_2ADDR:
464 case OP_XOR_LONG_2ADDR:
465 case OP_SHL_LONG_2ADDR:
466 case OP_SHR_LONG_2ADDR:
467 case OP_USHR_LONG_2ADDR:
468 case OP_ADD_FLOAT_2ADDR:
469 case OP_SUB_FLOAT_2ADDR:
470 case OP_MUL_FLOAT_2ADDR:
471 case OP_DIV_FLOAT_2ADDR:
472 case OP_REM_FLOAT_2ADDR:
473 case OP_ADD_DOUBLE_2ADDR:
474 case OP_SUB_DOUBLE_2ADDR:
475 case OP_MUL_DOUBLE_2ADDR:
476 case OP_DIV_DOUBLE_2ADDR:
477 case OP_REM_DOUBLE_2ADDR:
478 case OP_ADD_INT_LIT16:
479 case OP_RSUB_INT:
480 case OP_MUL_INT_LIT16:
481 case OP_AND_INT_LIT16:
482 case OP_OR_INT_LIT16:
483 case OP_XOR_INT_LIT16:
484 case OP_ADD_INT_LIT8:
485 case OP_RSUB_INT_LIT8:
486 case OP_MUL_INT_LIT8:
487 case OP_AND_INT_LIT8:
488 case OP_OR_INT_LIT8:
489 case OP_XOR_INT_LIT8:
490 case OP_SHL_INT_LIT8:
491 case OP_SHR_INT_LIT8:
492 case OP_USHR_INT_LIT8:
493 flags = kInstrCanContinue;
494 break;
495
496 /* these don't affect the PC, but can cause exceptions */
497 case OP_CONST_STRING:
498 case OP_CONST_STRING_JUMBO:
499 case OP_CONST_CLASS:
500 case OP_MONITOR_ENTER:
501 case OP_MONITOR_EXIT:
502 case OP_CHECK_CAST:
503 case OP_INSTANCE_OF:
504 case OP_ARRAY_LENGTH:
505 case OP_NEW_INSTANCE:
506 case OP_NEW_ARRAY:
507 case OP_FILLED_NEW_ARRAY:
508 case OP_FILLED_NEW_ARRAY_RANGE:
509 case OP_AGET:
510 case OP_AGET_BOOLEAN:
511 case OP_AGET_BYTE:
512 case OP_AGET_CHAR:
513 case OP_AGET_SHORT:
514 case OP_AGET_WIDE:
515 case OP_AGET_OBJECT:
516 case OP_APUT:
517 case OP_APUT_BOOLEAN:
518 case OP_APUT_BYTE:
519 case OP_APUT_CHAR:
520 case OP_APUT_SHORT:
521 case OP_APUT_WIDE:
522 case OP_APUT_OBJECT:
523 case OP_IGET:
524 case OP_IGET_BOOLEAN:
525 case OP_IGET_BYTE:
526 case OP_IGET_CHAR:
527 case OP_IGET_SHORT:
528 case OP_IGET_WIDE:
529 case OP_IGET_OBJECT:
530 case OP_IPUT:
531 case OP_IPUT_BOOLEAN:
532 case OP_IPUT_BYTE:
533 case OP_IPUT_CHAR:
534 case OP_IPUT_SHORT:
535 case OP_IPUT_WIDE:
536 case OP_IPUT_OBJECT:
537 case OP_SGET:
538 case OP_SGET_BOOLEAN:
539 case OP_SGET_BYTE:
540 case OP_SGET_CHAR:
541 case OP_SGET_SHORT:
542 case OP_SGET_WIDE:
543 case OP_SGET_OBJECT:
544 case OP_SPUT:
545 case OP_SPUT_BOOLEAN:
546 case OP_SPUT_BYTE:
547 case OP_SPUT_CHAR:
548 case OP_SPUT_SHORT:
549 case OP_SPUT_WIDE:
550 case OP_SPUT_OBJECT:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800551 case OP_DIV_INT:
552 case OP_REM_INT:
553 case OP_DIV_LONG:
554 case OP_REM_LONG:
555 case OP_DIV_INT_2ADDR:
556 case OP_REM_INT_2ADDR:
557 case OP_DIV_LONG_2ADDR:
558 case OP_REM_LONG_2ADDR:
559 case OP_DIV_INT_LIT16:
560 case OP_REM_INT_LIT16:
561 case OP_DIV_INT_LIT8:
562 case OP_REM_INT_LIT8:
563 flags = kInstrCanContinue | kInstrCanThrow;
564 break;
565
Ben Chengba4fc8b2009-06-01 13:00:29 -0700566 case OP_INVOKE_VIRTUAL:
567 case OP_INVOKE_VIRTUAL_RANGE:
568 case OP_INVOKE_SUPER:
569 case OP_INVOKE_SUPER_RANGE:
570 case OP_INVOKE_DIRECT:
571 case OP_INVOKE_DIRECT_RANGE:
572 case OP_INVOKE_STATIC:
573 case OP_INVOKE_STATIC_RANGE:
574 case OP_INVOKE_INTERFACE:
575 case OP_INVOKE_INTERFACE_RANGE:
576 flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
577 break;
578
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800579 case OP_RETURN_VOID:
580 case OP_RETURN:
581 case OP_RETURN_WIDE:
582 case OP_RETURN_OBJECT:
583 flags = kInstrCanReturn;
584 break;
585
586 case OP_THROW:
587 flags = kInstrCanThrow;
588 break;
589
590 /* unconditional branches */
591 case OP_GOTO:
592 case OP_GOTO_16:
593 case OP_GOTO_32:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700594 flags = kInstrCanBranch | kInstrUnconditional;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800595 break;
596
597 /* conditional branches */
598 case OP_IF_EQ:
599 case OP_IF_NE:
600 case OP_IF_LT:
601 case OP_IF_GE:
602 case OP_IF_GT:
603 case OP_IF_LE:
604 case OP_IF_EQZ:
605 case OP_IF_NEZ:
606 case OP_IF_LTZ:
607 case OP_IF_GEZ:
608 case OP_IF_GTZ:
609 case OP_IF_LEZ:
610 flags = kInstrCanBranch | kInstrCanContinue;
611 break;
612
613 /* switch statements; if value not in switch, it continues */
614 case OP_PACKED_SWITCH:
615 case OP_SPARSE_SWITCH:
616 flags = kInstrCanSwitch | kInstrCanContinue;
617 break;
618
Andy McFaddenb51ea112009-05-08 16:50:17 -0700619 /* verifier/optimizer-generated instructions */
Andy McFadden3a1aedb2009-05-07 13:30:23 -0700620 case OP_THROW_VERIFICATION_ERROR:
621 flags = kInstrCanThrow;
622 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800623 case OP_EXECUTE_INLINE:
Andy McFaddenb0a05412009-11-19 10:23:41 -0800624 case OP_EXECUTE_INLINE_RANGE:
625 flags = kInstrCanContinue | kInstrCanThrow;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800626 break;
627 case OP_IGET_QUICK:
628 case OP_IGET_WIDE_QUICK:
629 case OP_IGET_OBJECT_QUICK:
630 case OP_IPUT_QUICK:
631 case OP_IPUT_WIDE_QUICK:
632 case OP_IPUT_OBJECT_QUICK:
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700633 case OP_IGET_VOLATILE:
634 case OP_IPUT_VOLATILE:
635 case OP_SGET_VOLATILE:
636 case OP_SPUT_VOLATILE:
637 case OP_IGET_OBJECT_VOLATILE:
638 case OP_IPUT_OBJECT_VOLATILE:
639 case OP_SGET_OBJECT_VOLATILE:
640 case OP_SPUT_OBJECT_VOLATILE:
Andy McFadden53878242010-03-05 07:24:27 -0800641 case OP_IGET_WIDE_VOLATILE:
642 case OP_IPUT_WIDE_VOLATILE:
643 case OP_SGET_WIDE_VOLATILE:
644 case OP_SPUT_WIDE_VOLATILE:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700645 flags = kInstrCanContinue | kInstrCanThrow;
646 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800647 case OP_INVOKE_VIRTUAL_QUICK:
648 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
649 case OP_INVOKE_SUPER_QUICK:
650 case OP_INVOKE_SUPER_QUICK_RANGE:
651 case OP_INVOKE_DIRECT_EMPTY:
Ben Chengba4fc8b2009-06-01 13:00:29 -0700652 flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800653 break;
Andy McFadden291758c2010-09-10 08:04:52 -0700654 case OP_RETURN_VOID_BARRIER:
655 flags = kInstrCanReturn;
656 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800657
Andy McFadden96516932009-10-28 17:39:02 -0700658 /* these should never appear when scanning code */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800659 case OP_UNUSED_3E:
660 case OP_UNUSED_3F:
661 case OP_UNUSED_40:
662 case OP_UNUSED_41:
663 case OP_UNUSED_42:
664 case OP_UNUSED_43:
665 case OP_UNUSED_73:
666 case OP_UNUSED_79:
667 case OP_UNUSED_7A:
Andy McFadden96516932009-10-28 17:39:02 -0700668 case OP_BREAKPOINT:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800669 case OP_UNUSED_FF:
670 break;
671
672 /*
673 * DO NOT add a "default" clause here. Without it the compiler will
674 * complain if an instruction is missing (which is desirable).
675 */
676 }
677
678 instrFlags[opc] = flags;
679 }
680
681 return instrFlags;
682}
683
684/*
685 * Allocate and populate a 256-element array with instruction formats.
686 * Used in conjunction with dexDecodeInstruction.
687 */
688InstructionFormat* dexCreateInstrFormatTable(void)
689{
690 InstructionFormat* instFmt;
691 int i;
692
693 instFmt = malloc(sizeof(InstructionFormat) * kNumDalvikInstructions);
694 if (instFmt == NULL)
695 return NULL;
696
697 for (i = 0; i < kNumDalvikInstructions; i++) {
698 OpCode opc = (OpCode) i;
699 InstructionFormat fmt = kFmtUnknown;
700
701 switch (opc) {
702 case OP_GOTO:
703 fmt = kFmt10t;
704 break;
705 case OP_NOP:
706 case OP_RETURN_VOID:
707 fmt = kFmt10x;
708 break;
709 case OP_CONST_4:
710 fmt = kFmt11n;
711 break;
712 case OP_CONST_HIGH16:
713 case OP_CONST_WIDE_HIGH16:
714 fmt = kFmt21h;
715 break;
716 case OP_MOVE_RESULT:
717 case OP_MOVE_RESULT_WIDE:
718 case OP_MOVE_RESULT_OBJECT:
719 case OP_MOVE_EXCEPTION:
720 case OP_RETURN:
721 case OP_RETURN_WIDE:
722 case OP_RETURN_OBJECT:
723 case OP_MONITOR_ENTER:
724 case OP_MONITOR_EXIT:
725 case OP_THROW:
726 fmt = kFmt11x;
727 break;
728 case OP_MOVE:
729 case OP_MOVE_WIDE:
730 case OP_MOVE_OBJECT:
731 case OP_ARRAY_LENGTH:
732 case OP_NEG_INT:
733 case OP_NOT_INT:
734 case OP_NEG_LONG:
735 case OP_NOT_LONG:
736 case OP_NEG_FLOAT:
737 case OP_NEG_DOUBLE:
738 case OP_INT_TO_LONG:
739 case OP_INT_TO_FLOAT:
740 case OP_INT_TO_DOUBLE:
741 case OP_LONG_TO_INT:
742 case OP_LONG_TO_FLOAT:
743 case OP_LONG_TO_DOUBLE:
744 case OP_FLOAT_TO_INT:
745 case OP_FLOAT_TO_LONG:
746 case OP_FLOAT_TO_DOUBLE:
747 case OP_DOUBLE_TO_INT:
748 case OP_DOUBLE_TO_LONG:
749 case OP_DOUBLE_TO_FLOAT:
750 case OP_INT_TO_BYTE:
751 case OP_INT_TO_CHAR:
752 case OP_INT_TO_SHORT:
753 case OP_ADD_INT_2ADDR:
754 case OP_SUB_INT_2ADDR:
755 case OP_MUL_INT_2ADDR:
756 case OP_DIV_INT_2ADDR:
757 case OP_REM_INT_2ADDR:
758 case OP_AND_INT_2ADDR:
759 case OP_OR_INT_2ADDR:
760 case OP_XOR_INT_2ADDR:
761 case OP_SHL_INT_2ADDR:
762 case OP_SHR_INT_2ADDR:
763 case OP_USHR_INT_2ADDR:
764 case OP_ADD_LONG_2ADDR:
765 case OP_SUB_LONG_2ADDR:
766 case OP_MUL_LONG_2ADDR:
767 case OP_DIV_LONG_2ADDR:
768 case OP_REM_LONG_2ADDR:
769 case OP_AND_LONG_2ADDR:
770 case OP_OR_LONG_2ADDR:
771 case OP_XOR_LONG_2ADDR:
772 case OP_SHL_LONG_2ADDR:
773 case OP_SHR_LONG_2ADDR:
774 case OP_USHR_LONG_2ADDR:
775 case OP_ADD_FLOAT_2ADDR:
776 case OP_SUB_FLOAT_2ADDR:
777 case OP_MUL_FLOAT_2ADDR:
778 case OP_DIV_FLOAT_2ADDR:
779 case OP_REM_FLOAT_2ADDR:
780 case OP_ADD_DOUBLE_2ADDR:
781 case OP_SUB_DOUBLE_2ADDR:
782 case OP_MUL_DOUBLE_2ADDR:
783 case OP_DIV_DOUBLE_2ADDR:
784 case OP_REM_DOUBLE_2ADDR:
785 fmt = kFmt12x;
786 break;
787 case OP_GOTO_16:
788 fmt = kFmt20t;
789 break;
790 case OP_GOTO_32:
791 fmt = kFmt30t;
792 break;
793 case OP_CONST_STRING:
794 case OP_CONST_CLASS:
795 case OP_CHECK_CAST:
796 case OP_NEW_INSTANCE:
797 case OP_SGET:
798 case OP_SGET_WIDE:
799 case OP_SGET_OBJECT:
800 case OP_SGET_BOOLEAN:
801 case OP_SGET_BYTE:
802 case OP_SGET_CHAR:
803 case OP_SGET_SHORT:
804 case OP_SPUT:
805 case OP_SPUT_WIDE:
806 case OP_SPUT_OBJECT:
807 case OP_SPUT_BOOLEAN:
808 case OP_SPUT_BYTE:
809 case OP_SPUT_CHAR:
810 case OP_SPUT_SHORT:
811 fmt = kFmt21c;
812 break;
813 case OP_CONST_16:
814 case OP_CONST_WIDE_16:
815 fmt = kFmt21s;
816 break;
817 case OP_IF_EQZ:
818 case OP_IF_NEZ:
819 case OP_IF_LTZ:
820 case OP_IF_GEZ:
821 case OP_IF_GTZ:
822 case OP_IF_LEZ:
823 fmt = kFmt21t;
824 break;
825 case OP_FILL_ARRAY_DATA:
826 case OP_PACKED_SWITCH:
827 case OP_SPARSE_SWITCH:
828 fmt = kFmt31t;
829 break;
830 case OP_ADD_INT_LIT8:
831 case OP_RSUB_INT_LIT8:
832 case OP_MUL_INT_LIT8:
833 case OP_DIV_INT_LIT8:
834 case OP_REM_INT_LIT8:
835 case OP_AND_INT_LIT8:
836 case OP_OR_INT_LIT8:
837 case OP_XOR_INT_LIT8:
838 case OP_SHL_INT_LIT8:
839 case OP_SHR_INT_LIT8:
840 case OP_USHR_INT_LIT8:
841 fmt = kFmt22b;
842 break;
843 case OP_INSTANCE_OF:
844 case OP_NEW_ARRAY:
845 case OP_IGET:
846 case OP_IGET_WIDE:
847 case OP_IGET_OBJECT:
848 case OP_IGET_BOOLEAN:
849 case OP_IGET_BYTE:
850 case OP_IGET_CHAR:
851 case OP_IGET_SHORT:
852 case OP_IPUT:
853 case OP_IPUT_WIDE:
854 case OP_IPUT_OBJECT:
855 case OP_IPUT_BOOLEAN:
856 case OP_IPUT_BYTE:
857 case OP_IPUT_CHAR:
858 case OP_IPUT_SHORT:
859 fmt = kFmt22c;
860 break;
861 case OP_ADD_INT_LIT16:
862 case OP_RSUB_INT:
863 case OP_MUL_INT_LIT16:
864 case OP_DIV_INT_LIT16:
865 case OP_REM_INT_LIT16:
866 case OP_AND_INT_LIT16:
867 case OP_OR_INT_LIT16:
868 case OP_XOR_INT_LIT16:
869 fmt = kFmt22s;
870 break;
871 case OP_IF_EQ:
872 case OP_IF_NE:
873 case OP_IF_LT:
874 case OP_IF_GE:
875 case OP_IF_GT:
876 case OP_IF_LE:
877 fmt = kFmt22t;
878 break;
879 case OP_MOVE_FROM16:
880 case OP_MOVE_WIDE_FROM16:
881 case OP_MOVE_OBJECT_FROM16:
882 fmt = kFmt22x;
883 break;
884 case OP_CMPL_FLOAT:
885 case OP_CMPG_FLOAT:
886 case OP_CMPL_DOUBLE:
887 case OP_CMPG_DOUBLE:
888 case OP_CMP_LONG:
889 case OP_AGET:
890 case OP_AGET_WIDE:
891 case OP_AGET_OBJECT:
892 case OP_AGET_BOOLEAN:
893 case OP_AGET_BYTE:
894 case OP_AGET_CHAR:
895 case OP_AGET_SHORT:
896 case OP_APUT:
897 case OP_APUT_WIDE:
898 case OP_APUT_OBJECT:
899 case OP_APUT_BOOLEAN:
900 case OP_APUT_BYTE:
901 case OP_APUT_CHAR:
902 case OP_APUT_SHORT:
903 case OP_ADD_INT:
904 case OP_SUB_INT:
905 case OP_MUL_INT:
906 case OP_DIV_INT:
907 case OP_REM_INT:
908 case OP_AND_INT:
909 case OP_OR_INT:
910 case OP_XOR_INT:
911 case OP_SHL_INT:
912 case OP_SHR_INT:
913 case OP_USHR_INT:
914 case OP_ADD_LONG:
915 case OP_SUB_LONG:
916 case OP_MUL_LONG:
917 case OP_DIV_LONG:
918 case OP_REM_LONG:
919 case OP_AND_LONG:
920 case OP_OR_LONG:
921 case OP_XOR_LONG:
922 case OP_SHL_LONG:
923 case OP_SHR_LONG:
924 case OP_USHR_LONG:
925 case OP_ADD_FLOAT:
926 case OP_SUB_FLOAT:
927 case OP_MUL_FLOAT:
928 case OP_DIV_FLOAT:
929 case OP_REM_FLOAT:
930 case OP_ADD_DOUBLE:
931 case OP_SUB_DOUBLE:
932 case OP_MUL_DOUBLE:
933 case OP_DIV_DOUBLE:
934 case OP_REM_DOUBLE:
935 fmt = kFmt23x;
936 break;
937 case OP_CONST:
938 case OP_CONST_WIDE_32:
939 fmt = kFmt31i;
940 break;
941 case OP_CONST_STRING_JUMBO:
942 fmt = kFmt31c;
943 break;
944 case OP_MOVE_16:
945 case OP_MOVE_WIDE_16:
946 case OP_MOVE_OBJECT_16:
947 fmt = kFmt32x;
948 break;
949 case OP_FILLED_NEW_ARRAY:
950 case OP_INVOKE_VIRTUAL:
951 case OP_INVOKE_SUPER:
952 case OP_INVOKE_DIRECT:
953 case OP_INVOKE_STATIC:
954 case OP_INVOKE_INTERFACE:
955 fmt = kFmt35c;
956 break;
957 case OP_FILLED_NEW_ARRAY_RANGE:
958 case OP_INVOKE_VIRTUAL_RANGE:
959 case OP_INVOKE_SUPER_RANGE:
960 case OP_INVOKE_DIRECT_RANGE:
961 case OP_INVOKE_STATIC_RANGE:
962 case OP_INVOKE_INTERFACE_RANGE:
963 fmt = kFmt3rc;
964 break;
965 case OP_CONST_WIDE:
966 fmt = kFmt51l;
967 break;
968
969 /*
970 * Optimized instructions.
971 */
Andy McFadden3a1aedb2009-05-07 13:30:23 -0700972 case OP_THROW_VERIFICATION_ERROR:
973 fmt = kFmt20bc;
974 break;
Andy McFadden53878242010-03-05 07:24:27 -0800975 case OP_IGET_WIDE_VOLATILE:
976 case OP_IPUT_WIDE_VOLATILE:
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700977 case OP_IGET_VOLATILE:
978 case OP_IPUT_VOLATILE:
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700979 case OP_IGET_OBJECT_VOLATILE:
980 case OP_IPUT_OBJECT_VOLATILE:
buzbeeddc7d292010-09-02 17:16:24 -0700981 fmt = kFmt22c;
982 break;
Andy McFaddenc35a2ef2010-06-17 12:36:00 -0700983 case OP_SGET_OBJECT_VOLATILE:
984 case OP_SPUT_OBJECT_VOLATILE:
buzbeeddc7d292010-09-02 17:16:24 -0700985 case OP_SGET_VOLATILE:
986 case OP_SPUT_VOLATILE:
987 case OP_SGET_WIDE_VOLATILE:
988 case OP_SPUT_WIDE_VOLATILE:
989 fmt = kFmt21c;
Andy McFadden53878242010-03-05 07:24:27 -0800990 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800991 case OP_IGET_QUICK:
992 case OP_IGET_WIDE_QUICK:
993 case OP_IGET_OBJECT_QUICK:
994 case OP_IPUT_QUICK:
995 case OP_IPUT_WIDE_QUICK:
996 case OP_IPUT_OBJECT_QUICK:
997 fmt = kFmt22cs;
998 break;
999 case OP_INVOKE_VIRTUAL_QUICK:
1000 case OP_INVOKE_SUPER_QUICK:
1001 fmt = kFmt35ms;
1002 break;
1003 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
1004 case OP_INVOKE_SUPER_QUICK_RANGE:
1005 fmt = kFmt3rms;
1006 break;
1007 case OP_EXECUTE_INLINE:
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001008 fmt = kFmt35mi;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001009 break;
Andy McFaddenb0a05412009-11-19 10:23:41 -08001010 case OP_EXECUTE_INLINE_RANGE:
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001011 fmt = kFmt3rmi;
Andy McFaddenb0a05412009-11-19 10:23:41 -08001012 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001013 case OP_INVOKE_DIRECT_EMPTY:
1014 fmt = kFmt35c;
1015 break;
Andy McFadden291758c2010-09-10 08:04:52 -07001016 case OP_RETURN_VOID_BARRIER:
1017 fmt = kFmt10x;
1018 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001019
Andy McFadden96516932009-10-28 17:39:02 -07001020 /* these should never appear when scanning code */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001021 case OP_UNUSED_3E:
1022 case OP_UNUSED_3F:
1023 case OP_UNUSED_40:
1024 case OP_UNUSED_41:
1025 case OP_UNUSED_42:
1026 case OP_UNUSED_43:
1027 case OP_UNUSED_73:
1028 case OP_UNUSED_79:
1029 case OP_UNUSED_7A:
Andy McFadden96516932009-10-28 17:39:02 -07001030 case OP_BREAKPOINT:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001031 case OP_UNUSED_FF:
1032 fmt = kFmtUnknown;
1033 break;
1034
1035 /*
1036 * DO NOT add a "default" clause here. Without it the compiler will
1037 * complain if an instruction is missing (which is desirable).
1038 */
1039 }
1040
1041 instFmt[opc] = fmt;
1042 }
1043
1044 return instFmt;
1045}
1046
1047/*
1048 * Copied from InterpCore.h. Used for instruction decoding.
1049 */
1050#define FETCH(_offset) (insns[(_offset)])
1051#define INST_INST(_inst) ((_inst) & 0xff)
1052#define INST_A(_inst) (((u2)(_inst) >> 8) & 0x0f)
1053#define INST_B(_inst) ((u2)(_inst) >> 12)
1054#define INST_AA(_inst) ((_inst) >> 8)
1055
1056/*
1057 * Decode the instruction pointed to by "insns".
1058 *
1059 * Fills out the pieces of "pDec" that are affected by the current
1060 * instruction. Does not touch anything else.
1061 */
1062void dexDecodeInstruction(const InstructionFormat* fmts, const u2* insns,
1063 DecodedInstruction* pDec)
1064{
1065 u2 inst = *insns;
1066
1067 pDec->opCode = (OpCode) INST_INST(inst);
1068
1069 switch (dexGetInstrFormat(fmts, pDec->opCode)) {
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001070 case kFmt10x: // op
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001071 /* nothing to do; copy the AA bits out for the verifier */
1072 pDec->vA = INST_AA(inst);
1073 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001074 case kFmt12x: // op vA, vB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001075 pDec->vA = INST_A(inst);
1076 pDec->vB = INST_B(inst);
1077 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001078 case kFmt11n: // op vA, #+B
Carl Shapirode750892010-06-08 16:37:12 -07001079 pDec->vA = INST_A(inst);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001080 pDec->vB = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
1081 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001082 case kFmt11x: // op vAA
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001083 pDec->vA = INST_AA(inst);
1084 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001085 case kFmt10t: // op +AA
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001086 pDec->vA = (s1) INST_AA(inst); // sign-extend 8-bit value
1087 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001088 case kFmt20t: // op +AAAA
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001089 pDec->vA = (s2) FETCH(1); // sign-extend 16-bit value
1090 break;
Andy McFaddend3250112010-11-03 14:32:42 -07001091 case kFmt20bc: // [opt] op AA, thing@BBBB
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001092 case kFmt21c: // op vAA, thing@BBBB
1093 case kFmt22x: // op vAA, vBBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001094 pDec->vA = INST_AA(inst);
1095 pDec->vB = FETCH(1);
1096 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001097 case kFmt21s: // op vAA, #+BBBB
1098 case kFmt21t: // op vAA, +BBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001099 pDec->vA = INST_AA(inst);
1100 pDec->vB = (s2) FETCH(1); // sign-extend 16-bit value
1101 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001102 case kFmt21h: // op vAA, #+BBBB0000[00000000]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001103 pDec->vA = INST_AA(inst);
1104 /*
1105 * The value should be treated as right-zero-extended, but we don't
1106 * actually do that here. Among other things, we don't know if it's
1107 * the top bits of a 32- or 64-bit value.
1108 */
1109 pDec->vB = FETCH(1);
1110 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001111 case kFmt23x: // op vAA, vBB, vCC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001112 pDec->vA = INST_AA(inst);
1113 pDec->vB = FETCH(1) & 0xff;
1114 pDec->vC = FETCH(1) >> 8;
1115 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001116 case kFmt22b: // op vAA, vBB, #+CC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001117 pDec->vA = INST_AA(inst);
1118 pDec->vB = FETCH(1) & 0xff;
1119 pDec->vC = (s1) (FETCH(1) >> 8); // sign-extend 8-bit value
1120 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001121 case kFmt22s: // op vA, vB, #+CCCC
1122 case kFmt22t: // op vA, vB, +CCCC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001123 pDec->vA = INST_A(inst);
1124 pDec->vB = INST_B(inst);
1125 pDec->vC = (s2) FETCH(1); // sign-extend 16-bit value
1126 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001127 case kFmt22c: // op vA, vB, thing@CCCC
1128 case kFmt22cs: // [opt] op vA, vB, field offset CCCC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001129 pDec->vA = INST_A(inst);
1130 pDec->vB = INST_B(inst);
1131 pDec->vC = FETCH(1);
1132 break;
1133 case kFmt30t: // op +AAAAAAAA
1134 pDec->vA = FETCH(1) | ((u4) FETCH(2) << 16); // signed 32-bit value
1135 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001136 case kFmt31t: // op vAA, +BBBBBBBB
Andy McFaddend3250112010-11-03 14:32:42 -07001137 case kFmt31c: // op vAA, string@BBBBBBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001138 pDec->vA = INST_AA(inst);
1139 pDec->vB = FETCH(1) | ((u4) FETCH(2) << 16); // 32-bit value
1140 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001141 case kFmt32x: // op vAAAA, vBBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001142 pDec->vA = FETCH(1);
1143 pDec->vB = FETCH(2);
1144 break;
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001145 case kFmt31i: // op vAA, #+BBBBBBBB
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001146 pDec->vA = INST_AA(inst);
1147 pDec->vB = FETCH(1) | ((u4) FETCH(2) << 16);
1148 break;
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001149 case kFmt35c: // op {vC, vD, vE, vF, vG}, thing@BBBB
Andy McFadden3a1aedb2009-05-07 13:30:23 -07001150 case kFmt35ms: // [opt] invoke-virtual+super
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001151 {
1152 /*
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001153 * Note that the fields mentioned in the spec don't appear in
1154 * their "usual" positions here compared to most formats. This
1155 * was done so that the field names for the argument count and
1156 * reference index match between this format and the corresponding
1157 * range formats (3rc and friends).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001158 *
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001159 * Bottom line: The argument count is always in vA, and the
1160 * method constant is always in vB.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001161 */
1162 u2 regList;
1163 int i, count;
1164
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001165 pDec->vA = INST_B(inst); // This is labeled A in the spec.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001166 pDec->vB = FETCH(1);
1167 regList = FETCH(2);
1168
1169 if (pDec->vA > 5) {
1170 LOGW("Invalid arg count in 35c/35ms (%d)\n", pDec->vA);
1171 goto bail;
1172 }
1173 count = pDec->vA;
1174 if (count == 5) {
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001175 /*
1176 * Per note above, the 5th arg comes from the A field in the
1177 * instruction, but it's labeled G in the spec.
1178 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001179 pDec->arg[4] = INST_A(inst);
1180 count--;
1181 }
1182 for (i = 0; i < count; i++) {
1183 pDec->arg[i] = regList & 0x0f;
1184 regList >>= 4;
1185 }
1186 /* copy arg[0] to vC; we don't have vD/vE/vF, so ignore those */
1187 if (pDec->vA > 0)
1188 pDec->vC = pDec->arg[0];
1189 }
1190 break;
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001191 case kFmt35mi: // [opt] inline invoke
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001192 {
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001193 /* See note under case 35c, above. */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001194 u2 regList;
1195 int i;
1196
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001197 pDec->vA = INST_B(inst); // This is labeled A in the spec.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001198 pDec->vB = FETCH(1);
1199 regList = FETCH(2);
1200
1201 if (pDec->vA > 4) {
1202 LOGW("Invalid arg count in 3inline (%d)\n", pDec->vA);
1203 goto bail;
1204 }
1205 for (i = 0; i < (int) pDec->vA; i++) {
1206 pDec->arg[i] = regList & 0x0f;
1207 regList >>= 4;
1208 }
1209 /* copy arg[0] to vC; we don't have vD/vE/vF, so ignore those */
1210 if (pDec->vA > 0)
1211 pDec->vC = pDec->arg[0];
1212 }
1213 break;
1214 case kFmt35fs: // [opt] invoke-interface
1215 assert(false); // TODO
1216 break;
1217 case kFmt3rc: // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
1218 case kFmt3rms: // [opt] invoke-virtual+super/range
Dan Bornstein7b3e9b02010-11-09 17:15:10 -08001219 case kFmt3rmi: // [opt] execute-inline/range
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001220 pDec->vA = INST_AA(inst);
1221 pDec->vB = FETCH(1);
1222 pDec->vC = FETCH(2);
1223 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001224 case kFmt51l: // op vAA, #+BBBBBBBBBBBBBBBB
1225 pDec->vA = INST_AA(inst);
1226 pDec->vB_wide = FETCH(1);
1227 pDec->vB_wide |= (u8)FETCH(2) << 16;
1228 pDec->vB_wide |= (u8)FETCH(3) << 32;
1229 pDec->vB_wide |= (u8)FETCH(4) << 48;
1230 break;
1231 default:
1232 LOGW("Can't decode unexpected format %d (op=%d)\n",
1233 dexGetInstrFormat(fmts, pDec->opCode), pDec->opCode);
1234 assert(false);
1235 break;
1236 }
1237
1238bail:
1239 ;
1240}
1241
1242/*
1243 * Return the width of the specified instruction, or 0 if not defined. Also
1244 * works for special OP_NOP entries, including switch statement data tables
1245 * and array data.
1246 */
Andy McFadden228a6b02010-05-04 15:02:32 -07001247size_t dexGetInstrOrTableWidthAbs(const InstructionWidth* widths,
1248 const u2* insns)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001249{
Andy McFadden228a6b02010-05-04 15:02:32 -07001250 size_t width;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001251
1252 if (*insns == kPackedSwitchSignature) {
1253 width = 4 + insns[1] * 2;
1254 } else if (*insns == kSparseSwitchSignature) {
1255 width = 2 + insns[1] * 4;
1256 } else if (*insns == kArrayDataSignature) {
1257 u2 elemWidth = insns[1];
1258 u4 len = insns[2] | (((u4)insns[3]) << 16);
1259 width = 4 + (elemWidth * len + 1) / 2;
1260 } else {
1261 width = dexGetInstrWidthAbs(widths, INST_INST(insns[0]));
1262 }
1263 return width;
1264}