Merge "Use the generated opcode info tables." into dalvik-dev
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index 5949303..556dbc2 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -1097,7 +1097,7 @@
             }
         }
 
-        dexDecodeInstruction(&gInstrInfo, insns, &decInsn);
+        dexDecodeInstruction(insns, &decInsn);
         dumpInstruction(pDexFile, pCode, insnIdx, insnWidth, &decInsn);
 
         insns += insnWidth;
@@ -1891,10 +1891,7 @@
     }
 
     /* initialize some VM tables */
-    if (dexCreateInstructionInfoTables(&gInstrInfo)) {
-        fprintf(stderr, "Failed to construct instruction tables\n");
-        return 1;
-    }
+    dexGetInstructionInfoTables(&gInstrInfo);
 
     if (wantUsage) {
         usage();
@@ -1906,7 +1903,5 @@
         result |= process(argv[optind++]);
     }
 
-    dexFreeInstructionInfoTables(&gInstrInfo);
-
     return (result != 0);
 }
diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.c
index ab15c81..936bd01 100644
--- a/libdex/InstrUtils.c
+++ b/libdex/InstrUtils.c
@@ -25,9 +25,6 @@
 #include "InstrUtils.h"
 #include <stdlib.h>
 
-#if 0
-/* coming soon! */
-
 /*
  * Table that maps each opcode to the full width of instructions that
  * use that opcode, in (16-bit) code units. Unimplemented opcodes as
@@ -459,1379 +456,23 @@
     kIndexUnknown,
     // END(libdex-index-types)
 };
-#endif
 
 /*
- * Generate a table that holds the width of all instructions.
- *
- * Unimplemented instructions have a width of zero.
- *
- * I'm doing it with a giant switch statement because it's easier to
- * maintain and update than a static table with 256 unadorned integers,
- * and if we're missing a case gcc emits a "warning: enumeration value not
- * handled" message.
- *
- * (To save space in the binary we could generate a static table with a
- * command-line utility.)
+ * Global InstructionInfoTables struct.
  */
-InstructionWidth* dexCreateInstrWidthTable(void)
-{
-#ifdef __ARM_ARCH_7A__
-    /* hack to work around mysterious problem on emulator */
-    LOGD("creating instr width table\n");
-#endif
-    InstructionWidth* instrWidth;
-    int i;
-
-    instrWidth = malloc(sizeof(InstructionWidth) * kNumDalvikInstructions);
-    if (instrWidth == NULL)
-        return NULL;
-
-    for (i = 0; i < kNumDalvikInstructions; i++) {
-        OpCode opc = (OpCode) i;
-        int width = 0;
-
-        switch (opc) {
-        case OP_NOP:    /* note data for e.g. switch-* encoded "inside" a NOP */
-        case OP_MOVE:
-        case OP_MOVE_WIDE:
-        case OP_MOVE_OBJECT:
-        case OP_MOVE_RESULT:
-        case OP_MOVE_RESULT_WIDE:
-        case OP_MOVE_RESULT_OBJECT:
-        case OP_MOVE_EXCEPTION:
-        case OP_RETURN_VOID:
-        case OP_RETURN:
-        case OP_RETURN_WIDE:
-        case OP_RETURN_OBJECT:
-        case OP_CONST_4:
-        case OP_MONITOR_ENTER:
-        case OP_MONITOR_EXIT:
-        case OP_ARRAY_LENGTH:
-        case OP_THROW:
-        case OP_GOTO:
-        case OP_NEG_INT:
-        case OP_NOT_INT:
-        case OP_NEG_LONG:
-        case OP_NOT_LONG:
-        case OP_NEG_FLOAT:
-        case OP_NEG_DOUBLE:
-        case OP_INT_TO_LONG:
-        case OP_INT_TO_FLOAT:
-        case OP_INT_TO_DOUBLE:
-        case OP_LONG_TO_INT:
-        case OP_LONG_TO_FLOAT:
-        case OP_LONG_TO_DOUBLE:
-        case OP_FLOAT_TO_INT:
-        case OP_FLOAT_TO_LONG:
-        case OP_FLOAT_TO_DOUBLE:
-        case OP_DOUBLE_TO_INT:
-        case OP_DOUBLE_TO_LONG:
-        case OP_DOUBLE_TO_FLOAT:
-        case OP_INT_TO_BYTE:
-        case OP_INT_TO_CHAR:
-        case OP_INT_TO_SHORT:
-        case OP_ADD_INT_2ADDR:
-        case OP_SUB_INT_2ADDR:
-        case OP_MUL_INT_2ADDR:
-        case OP_DIV_INT_2ADDR:
-        case OP_REM_INT_2ADDR:
-        case OP_AND_INT_2ADDR:
-        case OP_OR_INT_2ADDR:
-        case OP_XOR_INT_2ADDR:
-        case OP_SHL_INT_2ADDR:
-        case OP_SHR_INT_2ADDR:
-        case OP_USHR_INT_2ADDR:
-        case OP_ADD_LONG_2ADDR:
-        case OP_SUB_LONG_2ADDR:
-        case OP_MUL_LONG_2ADDR:
-        case OP_DIV_LONG_2ADDR:
-        case OP_REM_LONG_2ADDR:
-        case OP_AND_LONG_2ADDR:
-        case OP_OR_LONG_2ADDR:
-        case OP_XOR_LONG_2ADDR:
-        case OP_SHL_LONG_2ADDR:
-        case OP_SHR_LONG_2ADDR:
-        case OP_USHR_LONG_2ADDR:
-        case OP_ADD_FLOAT_2ADDR:
-        case OP_SUB_FLOAT_2ADDR:
-        case OP_MUL_FLOAT_2ADDR:
-        case OP_DIV_FLOAT_2ADDR:
-        case OP_REM_FLOAT_2ADDR:
-        case OP_ADD_DOUBLE_2ADDR:
-        case OP_SUB_DOUBLE_2ADDR:
-        case OP_MUL_DOUBLE_2ADDR:
-        case OP_DIV_DOUBLE_2ADDR:
-        case OP_REM_DOUBLE_2ADDR:
-            width = 1;
-            break;
-
-        case OP_MOVE_FROM16:
-        case OP_MOVE_WIDE_FROM16:
-        case OP_MOVE_OBJECT_FROM16:
-        case OP_CONST_16:
-        case OP_CONST_HIGH16:
-        case OP_CONST_WIDE_16:
-        case OP_CONST_WIDE_HIGH16:
-        case OP_CONST_STRING:
-        case OP_CONST_CLASS:
-        case OP_CHECK_CAST:
-        case OP_INSTANCE_OF:
-        case OP_NEW_INSTANCE:
-        case OP_NEW_ARRAY:
-        case OP_CMPL_FLOAT:
-        case OP_CMPG_FLOAT:
-        case OP_CMPL_DOUBLE:
-        case OP_CMPG_DOUBLE:
-        case OP_CMP_LONG:
-        case OP_GOTO_16:
-        case OP_IF_EQ:
-        case OP_IF_NE:
-        case OP_IF_LT:
-        case OP_IF_GE:
-        case OP_IF_GT:
-        case OP_IF_LE:
-        case OP_IF_EQZ:
-        case OP_IF_NEZ:
-        case OP_IF_LTZ:
-        case OP_IF_GEZ:
-        case OP_IF_GTZ:
-        case OP_IF_LEZ:
-        case OP_AGET:
-        case OP_AGET_WIDE:
-        case OP_AGET_OBJECT:
-        case OP_AGET_BOOLEAN:
-        case OP_AGET_BYTE:
-        case OP_AGET_CHAR:
-        case OP_AGET_SHORT:
-        case OP_APUT:
-        case OP_APUT_WIDE:
-        case OP_APUT_OBJECT:
-        case OP_APUT_BOOLEAN:
-        case OP_APUT_BYTE:
-        case OP_APUT_CHAR:
-        case OP_APUT_SHORT:
-        case OP_IGET:
-        case OP_IGET_WIDE:
-        case OP_IGET_OBJECT:
-        case OP_IGET_BOOLEAN:
-        case OP_IGET_BYTE:
-        case OP_IGET_CHAR:
-        case OP_IGET_SHORT:
-        case OP_IPUT:
-        case OP_IPUT_WIDE:
-        case OP_IPUT_OBJECT:
-        case OP_IPUT_BOOLEAN:
-        case OP_IPUT_BYTE:
-        case OP_IPUT_CHAR:
-        case OP_IPUT_SHORT:
-        case OP_SGET:
-        case OP_SGET_WIDE:
-        case OP_SGET_OBJECT:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BYTE:
-        case OP_SGET_CHAR:
-        case OP_SGET_SHORT:
-        case OP_SPUT:
-        case OP_SPUT_WIDE:
-        case OP_SPUT_OBJECT:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_SHORT:
-        case OP_ADD_INT:
-        case OP_SUB_INT:
-        case OP_MUL_INT:
-        case OP_DIV_INT:
-        case OP_REM_INT:
-        case OP_AND_INT:
-        case OP_OR_INT:
-        case OP_XOR_INT:
-        case OP_SHL_INT:
-        case OP_SHR_INT:
-        case OP_USHR_INT:
-        case OP_ADD_LONG:
-        case OP_SUB_LONG:
-        case OP_MUL_LONG:
-        case OP_DIV_LONG:
-        case OP_REM_LONG:
-        case OP_AND_LONG:
-        case OP_OR_LONG:
-        case OP_XOR_LONG:
-        case OP_SHL_LONG:
-        case OP_SHR_LONG:
-        case OP_USHR_LONG:
-        case OP_ADD_FLOAT:
-        case OP_SUB_FLOAT:
-        case OP_MUL_FLOAT:
-        case OP_DIV_FLOAT:
-        case OP_REM_FLOAT:
-        case OP_ADD_DOUBLE:
-        case OP_SUB_DOUBLE:
-        case OP_MUL_DOUBLE:
-        case OP_DIV_DOUBLE:
-        case OP_REM_DOUBLE:
-        case OP_ADD_INT_LIT16:
-        case OP_RSUB_INT:
-        case OP_MUL_INT_LIT16:
-        case OP_DIV_INT_LIT16:
-        case OP_REM_INT_LIT16:
-        case OP_AND_INT_LIT16:
-        case OP_OR_INT_LIT16:
-        case OP_XOR_INT_LIT16:
-        case OP_ADD_INT_LIT8:
-        case OP_RSUB_INT_LIT8:
-        case OP_MUL_INT_LIT8:
-        case OP_DIV_INT_LIT8:
-        case OP_REM_INT_LIT8:
-        case OP_AND_INT_LIT8:
-        case OP_OR_INT_LIT8:
-        case OP_XOR_INT_LIT8:
-        case OP_SHL_INT_LIT8:
-        case OP_SHR_INT_LIT8:
-        case OP_USHR_INT_LIT8:
-            width = 2;
-            break;
-
-        case OP_MOVE_16:
-        case OP_MOVE_WIDE_16:
-        case OP_MOVE_OBJECT_16:
-        case OP_CONST:
-        case OP_CONST_WIDE_32:
-        case OP_CONST_STRING_JUMBO:
-        case OP_GOTO_32:
-        case OP_FILLED_NEW_ARRAY:
-        case OP_FILLED_NEW_ARRAY_RANGE:
-        case OP_FILL_ARRAY_DATA:
-        case OP_PACKED_SWITCH:
-        case OP_SPARSE_SWITCH:
-        case OP_INVOKE_VIRTUAL:
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_INTERFACE:
-        case OP_INVOKE_VIRTUAL_RANGE:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_INTERFACE_RANGE:
-            width = 3;
-            break;
-
-        case OP_CONST_WIDE:
-            width = 5;
-            break;
-
-        /*
-         * Optimized instructions.
-         */
-        case OP_RETURN_VOID_BARRIER:
-            width = 1;
-            break;
-        case OP_IGET_QUICK:
-        case OP_IGET_WIDE_QUICK:
-        case OP_IGET_OBJECT_QUICK:
-        case OP_IPUT_QUICK:
-        case OP_IPUT_WIDE_QUICK:
-        case OP_IPUT_OBJECT_QUICK:
-        case OP_IGET_VOLATILE:
-        case OP_IPUT_VOLATILE:
-        case OP_SGET_VOLATILE:
-        case OP_SPUT_VOLATILE:
-        case OP_IGET_OBJECT_VOLATILE:
-        case OP_IPUT_OBJECT_VOLATILE:
-        case OP_SGET_OBJECT_VOLATILE:
-        case OP_SPUT_OBJECT_VOLATILE:
-        case OP_IGET_WIDE_VOLATILE:
-        case OP_IPUT_WIDE_VOLATILE:
-        case OP_SGET_WIDE_VOLATILE:
-        case OP_SPUT_WIDE_VOLATILE:
-        case OP_THROW_VERIFICATION_ERROR:
-            width = 2;
-            break;
-        case OP_INVOKE_VIRTUAL_QUICK:
-        case OP_INVOKE_VIRTUAL_QUICK_RANGE:
-        case OP_INVOKE_SUPER_QUICK:
-        case OP_INVOKE_SUPER_QUICK_RANGE:
-        case OP_EXECUTE_INLINE:
-        case OP_EXECUTE_INLINE_RANGE:
-        case OP_INVOKE_DIRECT_EMPTY:
-            width = 3;
-            break;
-
-        /* these should never appear when scanning bytecode */
-        case OP_UNUSED_3E:
-        case OP_UNUSED_3F:
-        case OP_UNUSED_40:
-        case OP_UNUSED_41:
-        case OP_UNUSED_42:
-        case OP_UNUSED_43:
-        case OP_UNUSED_73:
-        case OP_UNUSED_79:
-        case OP_UNUSED_7A:
-        case OP_BREAKPOINT:
-        case OP_UNUSED_FF:
-            assert(width == 0);
-            break;
-
-        /*
-         * DO NOT add a "default" clause here.  Without it the compiler will
-         * complain if an instruction is missing (which is desirable).
-         */
-        }
-
-        instrWidth[opc] = width;
-    }
-
-    return instrWidth;
-}
+InstructionInfoTables gDexOpcodeInfo = {
+    gOpcodeFormatTable,
+    gOpcodeIndexTypeTable,
+    gOpcodeFlagsTable,
+    gOpcodeWidthTable
+};
 
 /*
- * Generate a table that holds instruction flags.
+ * Copy pointers to all of the instruction info tables into
+ * the given struct.
  */
-InstructionFlags* dexCreateInstrFlagsTable(void)
-{
-    InstructionFlags* instrFlags;
-    int i;
-
-    instrFlags = malloc(sizeof(InstructionFlags) * kNumDalvikInstructions);
-    if (instrFlags == NULL)
-        return NULL;
-
-    for (i = 0; i < kNumDalvikInstructions; i++) {
-        OpCode opc = (OpCode) i;
-        InstructionFlags flags = 0;
-
-        switch (opc) {
-        /* these don't affect the PC and can't cause an exception */
-        case OP_NOP:
-        case OP_MOVE:
-        case OP_MOVE_FROM16:
-        case OP_MOVE_16:
-        case OP_MOVE_WIDE:
-        case OP_MOVE_WIDE_FROM16:
-        case OP_MOVE_WIDE_16:
-        case OP_MOVE_OBJECT:
-        case OP_MOVE_OBJECT_FROM16:
-        case OP_MOVE_OBJECT_16:
-        case OP_MOVE_RESULT:
-        case OP_MOVE_RESULT_WIDE:
-        case OP_MOVE_RESULT_OBJECT:
-        case OP_MOVE_EXCEPTION:
-        case OP_CONST_4:
-        case OP_CONST_16:
-        case OP_CONST:
-        case OP_CONST_HIGH16:
-        case OP_CONST_WIDE_16:
-        case OP_CONST_WIDE_32:
-        case OP_CONST_WIDE:
-        case OP_CONST_WIDE_HIGH16:
-        case OP_FILL_ARRAY_DATA:
-        case OP_CMPL_FLOAT:
-        case OP_CMPG_FLOAT:
-        case OP_CMPL_DOUBLE:
-        case OP_CMPG_DOUBLE:
-        case OP_CMP_LONG:
-        case OP_NEG_INT:
-        case OP_NOT_INT:
-        case OP_NEG_LONG:
-        case OP_NOT_LONG:
-        case OP_NEG_FLOAT:
-        case OP_NEG_DOUBLE:
-        case OP_INT_TO_LONG:
-        case OP_INT_TO_FLOAT:
-        case OP_INT_TO_DOUBLE:
-        case OP_LONG_TO_INT:
-        case OP_LONG_TO_FLOAT:
-        case OP_LONG_TO_DOUBLE:
-        case OP_FLOAT_TO_INT:
-        case OP_FLOAT_TO_LONG:
-        case OP_FLOAT_TO_DOUBLE:
-        case OP_DOUBLE_TO_INT:
-        case OP_DOUBLE_TO_LONG:
-        case OP_DOUBLE_TO_FLOAT:
-        case OP_INT_TO_BYTE:
-        case OP_INT_TO_CHAR:
-        case OP_INT_TO_SHORT:
-        case OP_ADD_INT:
-        case OP_SUB_INT:
-        case OP_MUL_INT:
-        case OP_AND_INT:
-        case OP_OR_INT:
-        case OP_XOR_INT:
-        case OP_SHL_INT:
-        case OP_SHR_INT:
-        case OP_USHR_INT:
-        case OP_ADD_LONG:
-        case OP_SUB_LONG:
-        case OP_MUL_LONG:
-        case OP_AND_LONG:
-        case OP_OR_LONG:
-        case OP_XOR_LONG:
-        case OP_SHL_LONG:
-        case OP_SHR_LONG:
-        case OP_USHR_LONG:
-        case OP_ADD_FLOAT:
-        case OP_SUB_FLOAT:
-        case OP_MUL_FLOAT:
-        case OP_DIV_FLOAT:
-        case OP_REM_FLOAT:
-        case OP_ADD_DOUBLE:
-        case OP_SUB_DOUBLE:
-        case OP_MUL_DOUBLE:
-        case OP_DIV_DOUBLE:         // div by zero just returns NaN
-        case OP_REM_DOUBLE:
-        case OP_ADD_INT_2ADDR:
-        case OP_SUB_INT_2ADDR:
-        case OP_MUL_INT_2ADDR:
-        case OP_AND_INT_2ADDR:
-        case OP_OR_INT_2ADDR:
-        case OP_XOR_INT_2ADDR:
-        case OP_SHL_INT_2ADDR:
-        case OP_SHR_INT_2ADDR:
-        case OP_USHR_INT_2ADDR:
-        case OP_ADD_LONG_2ADDR:
-        case OP_SUB_LONG_2ADDR:
-        case OP_MUL_LONG_2ADDR:
-        case OP_AND_LONG_2ADDR:
-        case OP_OR_LONG_2ADDR:
-        case OP_XOR_LONG_2ADDR:
-        case OP_SHL_LONG_2ADDR:
-        case OP_SHR_LONG_2ADDR:
-        case OP_USHR_LONG_2ADDR:
-        case OP_ADD_FLOAT_2ADDR:
-        case OP_SUB_FLOAT_2ADDR:
-        case OP_MUL_FLOAT_2ADDR:
-        case OP_DIV_FLOAT_2ADDR:
-        case OP_REM_FLOAT_2ADDR:
-        case OP_ADD_DOUBLE_2ADDR:
-        case OP_SUB_DOUBLE_2ADDR:
-        case OP_MUL_DOUBLE_2ADDR:
-        case OP_DIV_DOUBLE_2ADDR:
-        case OP_REM_DOUBLE_2ADDR:
-        case OP_ADD_INT_LIT16:
-        case OP_RSUB_INT:
-        case OP_MUL_INT_LIT16:
-        case OP_AND_INT_LIT16:
-        case OP_OR_INT_LIT16:
-        case OP_XOR_INT_LIT16:
-        case OP_ADD_INT_LIT8:
-        case OP_RSUB_INT_LIT8:
-        case OP_MUL_INT_LIT8:
-        case OP_AND_INT_LIT8:
-        case OP_OR_INT_LIT8:
-        case OP_XOR_INT_LIT8:
-        case OP_SHL_INT_LIT8:
-        case OP_SHR_INT_LIT8:
-        case OP_USHR_INT_LIT8:
-            flags = kInstrCanContinue;
-            break;
-
-        /* these don't affect the PC, but can cause exceptions */
-        case OP_CONST_STRING:
-        case OP_CONST_STRING_JUMBO:
-        case OP_CONST_CLASS:
-        case OP_MONITOR_ENTER:
-        case OP_MONITOR_EXIT:
-        case OP_CHECK_CAST:
-        case OP_INSTANCE_OF:
-        case OP_ARRAY_LENGTH:
-        case OP_NEW_INSTANCE:
-        case OP_NEW_ARRAY:
-        case OP_FILLED_NEW_ARRAY:
-        case OP_FILLED_NEW_ARRAY_RANGE:
-        case OP_AGET:
-        case OP_AGET_BOOLEAN:
-        case OP_AGET_BYTE:
-        case OP_AGET_CHAR:
-        case OP_AGET_SHORT:
-        case OP_AGET_WIDE:
-        case OP_AGET_OBJECT:
-        case OP_APUT:
-        case OP_APUT_BOOLEAN:
-        case OP_APUT_BYTE:
-        case OP_APUT_CHAR:
-        case OP_APUT_SHORT:
-        case OP_APUT_WIDE:
-        case OP_APUT_OBJECT:
-        case OP_IGET:
-        case OP_IGET_BOOLEAN:
-        case OP_IGET_BYTE:
-        case OP_IGET_CHAR:
-        case OP_IGET_SHORT:
-        case OP_IGET_WIDE:
-        case OP_IGET_OBJECT:
-        case OP_IPUT:
-        case OP_IPUT_BOOLEAN:
-        case OP_IPUT_BYTE:
-        case OP_IPUT_CHAR:
-        case OP_IPUT_SHORT:
-        case OP_IPUT_WIDE:
-        case OP_IPUT_OBJECT:
-        case OP_SGET:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BYTE:
-        case OP_SGET_CHAR:
-        case OP_SGET_SHORT:
-        case OP_SGET_WIDE:
-        case OP_SGET_OBJECT:
-        case OP_SPUT:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_SHORT:
-        case OP_SPUT_WIDE:
-        case OP_SPUT_OBJECT:
-        case OP_DIV_INT:
-        case OP_REM_INT:
-        case OP_DIV_LONG:
-        case OP_REM_LONG:
-        case OP_DIV_INT_2ADDR:
-        case OP_REM_INT_2ADDR:
-        case OP_DIV_LONG_2ADDR:
-        case OP_REM_LONG_2ADDR:
-        case OP_DIV_INT_LIT16:
-        case OP_REM_INT_LIT16:
-        case OP_DIV_INT_LIT8:
-        case OP_REM_INT_LIT8:
-            flags = kInstrCanContinue | kInstrCanThrow;
-            break;
-
-        case OP_INVOKE_VIRTUAL:
-        case OP_INVOKE_VIRTUAL_RANGE:
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_INTERFACE:
-        case OP_INVOKE_INTERFACE_RANGE:
-            flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
-            break;
-
-        case OP_RETURN_VOID:
-        case OP_RETURN:
-        case OP_RETURN_WIDE:
-        case OP_RETURN_OBJECT:
-            flags = kInstrCanReturn;
-            break;
-
-        case OP_THROW:
-            flags = kInstrCanThrow;
-            break;
-
-        /* unconditional branches */
-        case OP_GOTO:
-        case OP_GOTO_16:
-        case OP_GOTO_32:
-            flags = kInstrCanBranch;
-            break;
-
-        /* conditional branches */
-        case OP_IF_EQ:
-        case OP_IF_NE:
-        case OP_IF_LT:
-        case OP_IF_GE:
-        case OP_IF_GT:
-        case OP_IF_LE:
-        case OP_IF_EQZ:
-        case OP_IF_NEZ:
-        case OP_IF_LTZ:
-        case OP_IF_GEZ:
-        case OP_IF_GTZ:
-        case OP_IF_LEZ:
-            flags = kInstrCanBranch | kInstrCanContinue;
-            break;
-
-        /* switch statements; if value not in switch, it continues */
-        case OP_PACKED_SWITCH:
-        case OP_SPARSE_SWITCH:
-            flags = kInstrCanSwitch | kInstrCanContinue;
-            break;
-
-        /* verifier/optimizer-generated instructions */
-        case OP_THROW_VERIFICATION_ERROR:
-            flags = kInstrCanThrow;
-            break;
-        case OP_EXECUTE_INLINE:
-        case OP_EXECUTE_INLINE_RANGE:
-            flags = kInstrCanContinue | kInstrCanThrow;
-            break;
-        case OP_IGET_QUICK:
-        case OP_IGET_WIDE_QUICK:
-        case OP_IGET_OBJECT_QUICK:
-        case OP_IPUT_QUICK:
-        case OP_IPUT_WIDE_QUICK:
-        case OP_IPUT_OBJECT_QUICK:
-        case OP_IGET_VOLATILE:
-        case OP_IPUT_VOLATILE:
-        case OP_SGET_VOLATILE:
-        case OP_SPUT_VOLATILE:
-        case OP_IGET_OBJECT_VOLATILE:
-        case OP_IPUT_OBJECT_VOLATILE:
-        case OP_SGET_OBJECT_VOLATILE:
-        case OP_SPUT_OBJECT_VOLATILE:
-        case OP_IGET_WIDE_VOLATILE:
-        case OP_IPUT_WIDE_VOLATILE:
-        case OP_SGET_WIDE_VOLATILE:
-        case OP_SPUT_WIDE_VOLATILE:
-            flags = kInstrCanContinue | kInstrCanThrow;
-            break;
-        case OP_INVOKE_VIRTUAL_QUICK:
-        case OP_INVOKE_VIRTUAL_QUICK_RANGE:
-        case OP_INVOKE_SUPER_QUICK:
-        case OP_INVOKE_SUPER_QUICK_RANGE:
-        case OP_INVOKE_DIRECT_EMPTY:
-            flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
-            break;
-        case OP_RETURN_VOID_BARRIER:
-            flags = kInstrCanReturn;
-            break;
-
-        /* these should never appear when scanning code */
-        case OP_UNUSED_3E:
-        case OP_UNUSED_3F:
-        case OP_UNUSED_40:
-        case OP_UNUSED_41:
-        case OP_UNUSED_42:
-        case OP_UNUSED_43:
-        case OP_UNUSED_73:
-        case OP_UNUSED_79:
-        case OP_UNUSED_7A:
-        case OP_BREAKPOINT:
-        case OP_UNUSED_FF:
-            break;
-
-        /*
-         * DO NOT add a "default" clause here.  Without it the compiler will
-         * complain if an instruction is missing (which is desirable).
-         */
-        }
-
-        instrFlags[opc] = flags;
-    }
-
-    return instrFlags;
-}
-
-/*
- * Allocate and populate a 256-element array with instruction formats.
- * Used in conjunction with dexDecodeInstruction.
- */
-InstructionFormat* dexCreateInstrFormatTable(void)
-{
-    InstructionFormat* instFmt;
-    int i;
-
-    instFmt = malloc(sizeof(InstructionFormat) * kNumDalvikInstructions);
-    if (instFmt == NULL)
-        return NULL;
-
-    for (i = 0; i < kNumDalvikInstructions; i++) {
-        OpCode opc = (OpCode) i;
-        InstructionFormat fmt = kFmt00x;
-
-        switch (opc) {
-        case OP_GOTO:
-            fmt = kFmt10t;
-            break;
-        case OP_NOP:
-        case OP_RETURN_VOID:
-            fmt = kFmt10x;
-            break;
-        case OP_CONST_4:
-            fmt = kFmt11n;
-            break;
-        case OP_CONST_HIGH16:
-        case OP_CONST_WIDE_HIGH16:
-            fmt = kFmt21h;
-            break;
-        case OP_MOVE_RESULT:
-        case OP_MOVE_RESULT_WIDE:
-        case OP_MOVE_RESULT_OBJECT:
-        case OP_MOVE_EXCEPTION:
-        case OP_RETURN:
-        case OP_RETURN_WIDE:
-        case OP_RETURN_OBJECT:
-        case OP_MONITOR_ENTER:
-        case OP_MONITOR_EXIT:
-        case OP_THROW:
-            fmt = kFmt11x;
-            break;
-        case OP_MOVE:
-        case OP_MOVE_WIDE:
-        case OP_MOVE_OBJECT:
-        case OP_ARRAY_LENGTH:
-        case OP_NEG_INT:
-        case OP_NOT_INT:
-        case OP_NEG_LONG:
-        case OP_NOT_LONG:
-        case OP_NEG_FLOAT:
-        case OP_NEG_DOUBLE:
-        case OP_INT_TO_LONG:
-        case OP_INT_TO_FLOAT:
-        case OP_INT_TO_DOUBLE:
-        case OP_LONG_TO_INT:
-        case OP_LONG_TO_FLOAT:
-        case OP_LONG_TO_DOUBLE:
-        case OP_FLOAT_TO_INT:
-        case OP_FLOAT_TO_LONG:
-        case OP_FLOAT_TO_DOUBLE:
-        case OP_DOUBLE_TO_INT:
-        case OP_DOUBLE_TO_LONG:
-        case OP_DOUBLE_TO_FLOAT:
-        case OP_INT_TO_BYTE:
-        case OP_INT_TO_CHAR:
-        case OP_INT_TO_SHORT:
-        case OP_ADD_INT_2ADDR:
-        case OP_SUB_INT_2ADDR:
-        case OP_MUL_INT_2ADDR:
-        case OP_DIV_INT_2ADDR:
-        case OP_REM_INT_2ADDR:
-        case OP_AND_INT_2ADDR:
-        case OP_OR_INT_2ADDR:
-        case OP_XOR_INT_2ADDR:
-        case OP_SHL_INT_2ADDR:
-        case OP_SHR_INT_2ADDR:
-        case OP_USHR_INT_2ADDR:
-        case OP_ADD_LONG_2ADDR:
-        case OP_SUB_LONG_2ADDR:
-        case OP_MUL_LONG_2ADDR:
-        case OP_DIV_LONG_2ADDR:
-        case OP_REM_LONG_2ADDR:
-        case OP_AND_LONG_2ADDR:
-        case OP_OR_LONG_2ADDR:
-        case OP_XOR_LONG_2ADDR:
-        case OP_SHL_LONG_2ADDR:
-        case OP_SHR_LONG_2ADDR:
-        case OP_USHR_LONG_2ADDR:
-        case OP_ADD_FLOAT_2ADDR:
-        case OP_SUB_FLOAT_2ADDR:
-        case OP_MUL_FLOAT_2ADDR:
-        case OP_DIV_FLOAT_2ADDR:
-        case OP_REM_FLOAT_2ADDR:
-        case OP_ADD_DOUBLE_2ADDR:
-        case OP_SUB_DOUBLE_2ADDR:
-        case OP_MUL_DOUBLE_2ADDR:
-        case OP_DIV_DOUBLE_2ADDR:
-        case OP_REM_DOUBLE_2ADDR:
-            fmt = kFmt12x;
-            break;
-        case OP_GOTO_16:
-            fmt = kFmt20t;
-            break;
-        case OP_GOTO_32:
-            fmt = kFmt30t;
-            break;
-        case OP_CONST_STRING:
-        case OP_CONST_CLASS:
-        case OP_CHECK_CAST:
-        case OP_NEW_INSTANCE:
-        case OP_SGET:
-        case OP_SGET_WIDE:
-        case OP_SGET_OBJECT:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BYTE:
-        case OP_SGET_CHAR:
-        case OP_SGET_SHORT:
-        case OP_SPUT:
-        case OP_SPUT_WIDE:
-        case OP_SPUT_OBJECT:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_SHORT:
-            fmt = kFmt21c;
-            break;
-        case OP_CONST_16:
-        case OP_CONST_WIDE_16:
-            fmt = kFmt21s;
-            break;
-        case OP_IF_EQZ:
-        case OP_IF_NEZ:
-        case OP_IF_LTZ:
-        case OP_IF_GEZ:
-        case OP_IF_GTZ:
-        case OP_IF_LEZ:
-            fmt = kFmt21t;
-            break;
-        case OP_FILL_ARRAY_DATA:
-        case OP_PACKED_SWITCH:
-        case OP_SPARSE_SWITCH:
-            fmt = kFmt31t;
-            break;
-        case OP_ADD_INT_LIT8:
-        case OP_RSUB_INT_LIT8:
-        case OP_MUL_INT_LIT8:
-        case OP_DIV_INT_LIT8:
-        case OP_REM_INT_LIT8:
-        case OP_AND_INT_LIT8:
-        case OP_OR_INT_LIT8:
-        case OP_XOR_INT_LIT8:
-        case OP_SHL_INT_LIT8:
-        case OP_SHR_INT_LIT8:
-        case OP_USHR_INT_LIT8:
-            fmt = kFmt22b;
-            break;
-        case OP_INSTANCE_OF:
-        case OP_NEW_ARRAY:
-        case OP_IGET:
-        case OP_IGET_WIDE:
-        case OP_IGET_OBJECT:
-        case OP_IGET_BOOLEAN:
-        case OP_IGET_BYTE:
-        case OP_IGET_CHAR:
-        case OP_IGET_SHORT:
-        case OP_IPUT:
-        case OP_IPUT_WIDE:
-        case OP_IPUT_OBJECT:
-        case OP_IPUT_BOOLEAN:
-        case OP_IPUT_BYTE:
-        case OP_IPUT_CHAR:
-        case OP_IPUT_SHORT:
-            fmt = kFmt22c;
-            break;
-        case OP_ADD_INT_LIT16:
-        case OP_RSUB_INT:
-        case OP_MUL_INT_LIT16:
-        case OP_DIV_INT_LIT16:
-        case OP_REM_INT_LIT16:
-        case OP_AND_INT_LIT16:
-        case OP_OR_INT_LIT16:
-        case OP_XOR_INT_LIT16:
-            fmt = kFmt22s;
-            break;
-        case OP_IF_EQ:
-        case OP_IF_NE:
-        case OP_IF_LT:
-        case OP_IF_GE:
-        case OP_IF_GT:
-        case OP_IF_LE:
-            fmt = kFmt22t;
-            break;
-        case OP_MOVE_FROM16:
-        case OP_MOVE_WIDE_FROM16:
-        case OP_MOVE_OBJECT_FROM16:
-            fmt = kFmt22x;
-            break;
-        case OP_CMPL_FLOAT:
-        case OP_CMPG_FLOAT:
-        case OP_CMPL_DOUBLE:
-        case OP_CMPG_DOUBLE:
-        case OP_CMP_LONG:
-        case OP_AGET:
-        case OP_AGET_WIDE:
-        case OP_AGET_OBJECT:
-        case OP_AGET_BOOLEAN:
-        case OP_AGET_BYTE:
-        case OP_AGET_CHAR:
-        case OP_AGET_SHORT:
-        case OP_APUT:
-        case OP_APUT_WIDE:
-        case OP_APUT_OBJECT:
-        case OP_APUT_BOOLEAN:
-        case OP_APUT_BYTE:
-        case OP_APUT_CHAR:
-        case OP_APUT_SHORT:
-        case OP_ADD_INT:
-        case OP_SUB_INT:
-        case OP_MUL_INT:
-        case OP_DIV_INT:
-        case OP_REM_INT:
-        case OP_AND_INT:
-        case OP_OR_INT:
-        case OP_XOR_INT:
-        case OP_SHL_INT:
-        case OP_SHR_INT:
-        case OP_USHR_INT:
-        case OP_ADD_LONG:
-        case OP_SUB_LONG:
-        case OP_MUL_LONG:
-        case OP_DIV_LONG:
-        case OP_REM_LONG:
-        case OP_AND_LONG:
-        case OP_OR_LONG:
-        case OP_XOR_LONG:
-        case OP_SHL_LONG:
-        case OP_SHR_LONG:
-        case OP_USHR_LONG:
-        case OP_ADD_FLOAT:
-        case OP_SUB_FLOAT:
-        case OP_MUL_FLOAT:
-        case OP_DIV_FLOAT:
-        case OP_REM_FLOAT:
-        case OP_ADD_DOUBLE:
-        case OP_SUB_DOUBLE:
-        case OP_MUL_DOUBLE:
-        case OP_DIV_DOUBLE:
-        case OP_REM_DOUBLE:
-            fmt = kFmt23x;
-            break;
-        case OP_CONST:
-        case OP_CONST_WIDE_32:
-            fmt = kFmt31i;
-            break;
-        case OP_CONST_STRING_JUMBO:
-            fmt = kFmt31c;
-            break;
-        case OP_MOVE_16:
-        case OP_MOVE_WIDE_16:
-        case OP_MOVE_OBJECT_16:
-            fmt = kFmt32x;
-            break;
-        case OP_FILLED_NEW_ARRAY:
-        case OP_INVOKE_VIRTUAL:
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_INTERFACE:
-            fmt = kFmt35c;
-            break;
-        case OP_FILLED_NEW_ARRAY_RANGE:
-        case OP_INVOKE_VIRTUAL_RANGE:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_INTERFACE_RANGE:
-            fmt = kFmt3rc;
-            break;
-        case OP_CONST_WIDE:
-            fmt = kFmt51l;
-            break;
-
-        /*
-         * Optimized instructions.
-         */
-        case OP_THROW_VERIFICATION_ERROR:
-            fmt = kFmt20bc;
-            break;
-        case OP_IGET_WIDE_VOLATILE:
-        case OP_IPUT_WIDE_VOLATILE:
-        case OP_IGET_VOLATILE:
-        case OP_IPUT_VOLATILE:
-        case OP_IGET_OBJECT_VOLATILE:
-        case OP_IPUT_OBJECT_VOLATILE:
-            fmt = kFmt22c;
-            break;
-        case OP_SGET_OBJECT_VOLATILE:
-        case OP_SPUT_OBJECT_VOLATILE:
-        case OP_SGET_VOLATILE:
-        case OP_SPUT_VOLATILE:
-        case OP_SGET_WIDE_VOLATILE:
-        case OP_SPUT_WIDE_VOLATILE:
-            fmt = kFmt21c;
-            break;
-        case OP_IGET_QUICK:
-        case OP_IGET_WIDE_QUICK:
-        case OP_IGET_OBJECT_QUICK:
-        case OP_IPUT_QUICK:
-        case OP_IPUT_WIDE_QUICK:
-        case OP_IPUT_OBJECT_QUICK:
-            fmt = kFmt22cs;
-            break;
-        case OP_INVOKE_VIRTUAL_QUICK:
-        case OP_INVOKE_SUPER_QUICK:
-            fmt = kFmt35ms;
-            break;
-        case OP_INVOKE_VIRTUAL_QUICK_RANGE:
-        case OP_INVOKE_SUPER_QUICK_RANGE:
-            fmt = kFmt3rms;
-            break;
-        case OP_EXECUTE_INLINE:
-            fmt = kFmt35mi;
-            break;
-        case OP_EXECUTE_INLINE_RANGE:
-            fmt = kFmt3rmi;
-            break;
-        case OP_INVOKE_DIRECT_EMPTY:
-            fmt = kFmt35c;
-            break;
-        case OP_RETURN_VOID_BARRIER:
-            fmt = kFmt10x;
-            break;
-
-        /* these should never appear when scanning code */
-        case OP_UNUSED_3E:
-        case OP_UNUSED_3F:
-        case OP_UNUSED_40:
-        case OP_UNUSED_41:
-        case OP_UNUSED_42:
-        case OP_UNUSED_43:
-        case OP_UNUSED_73:
-        case OP_UNUSED_79:
-        case OP_UNUSED_7A:
-        case OP_BREAKPOINT:
-        case OP_UNUSED_FF:
-            fmt = kFmt00x;
-            break;
-
-        /*
-         * DO NOT add a "default" clause here.  Without it the compiler will
-         * complain if an instruction is missing (which is desirable).
-         */
-        }
-
-        instFmt[opc] = fmt;
-    }
-
-    return instFmt;
-}
-
-/*
- * Allocate and populate an array with index types for all instructions.
- * Used in conjunction with dexDecodeInstruction.
- */
-InstructionIndexType* dexCreateInstrIndexTypeTable(void)
-{
-    InstructionIndexType* indexTypes;
-    int i;
-
-    indexTypes = malloc(sizeof(InstructionIndexType) * kNumDalvikInstructions);
-    if (indexTypes == NULL)
-        return NULL;
-
-    for (i = 0; i < kNumDalvikInstructions; i++) {
-        OpCode opc = (OpCode) i;
-        InstructionIndexType indexType = kIndexUnknown;
-
-        switch (opc) {
-        case OP_GOTO:
-        case OP_NOP:
-        case OP_RETURN_VOID:
-        case OP_CONST_4:
-        case OP_CONST_HIGH16:
-        case OP_CONST_WIDE_HIGH16:
-        case OP_MOVE_RESULT:
-        case OP_MOVE_RESULT_WIDE:
-        case OP_MOVE_RESULT_OBJECT:
-        case OP_MOVE_EXCEPTION:
-        case OP_RETURN:
-        case OP_RETURN_WIDE:
-        case OP_RETURN_OBJECT:
-        case OP_MONITOR_ENTER:
-        case OP_MONITOR_EXIT:
-        case OP_THROW:
-        case OP_MOVE:
-        case OP_MOVE_WIDE:
-        case OP_MOVE_OBJECT:
-        case OP_ARRAY_LENGTH:
-        case OP_NEG_INT:
-        case OP_NOT_INT:
-        case OP_NEG_LONG:
-        case OP_NOT_LONG:
-        case OP_NEG_FLOAT:
-        case OP_NEG_DOUBLE:
-        case OP_INT_TO_LONG:
-        case OP_INT_TO_FLOAT:
-        case OP_INT_TO_DOUBLE:
-        case OP_LONG_TO_INT:
-        case OP_LONG_TO_FLOAT:
-        case OP_LONG_TO_DOUBLE:
-        case OP_FLOAT_TO_INT:
-        case OP_FLOAT_TO_LONG:
-        case OP_FLOAT_TO_DOUBLE:
-        case OP_DOUBLE_TO_INT:
-        case OP_DOUBLE_TO_LONG:
-        case OP_DOUBLE_TO_FLOAT:
-        case OP_INT_TO_BYTE:
-        case OP_INT_TO_CHAR:
-        case OP_INT_TO_SHORT:
-        case OP_ADD_INT_2ADDR:
-        case OP_SUB_INT_2ADDR:
-        case OP_MUL_INT_2ADDR:
-        case OP_DIV_INT_2ADDR:
-        case OP_REM_INT_2ADDR:
-        case OP_AND_INT_2ADDR:
-        case OP_OR_INT_2ADDR:
-        case OP_XOR_INT_2ADDR:
-        case OP_SHL_INT_2ADDR:
-        case OP_SHR_INT_2ADDR:
-        case OP_USHR_INT_2ADDR:
-        case OP_ADD_LONG_2ADDR:
-        case OP_SUB_LONG_2ADDR:
-        case OP_MUL_LONG_2ADDR:
-        case OP_DIV_LONG_2ADDR:
-        case OP_REM_LONG_2ADDR:
-        case OP_AND_LONG_2ADDR:
-        case OP_OR_LONG_2ADDR:
-        case OP_XOR_LONG_2ADDR:
-        case OP_SHL_LONG_2ADDR:
-        case OP_SHR_LONG_2ADDR:
-        case OP_USHR_LONG_2ADDR:
-        case OP_ADD_FLOAT_2ADDR:
-        case OP_SUB_FLOAT_2ADDR:
-        case OP_MUL_FLOAT_2ADDR:
-        case OP_DIV_FLOAT_2ADDR:
-        case OP_REM_FLOAT_2ADDR:
-        case OP_ADD_DOUBLE_2ADDR:
-        case OP_SUB_DOUBLE_2ADDR:
-        case OP_MUL_DOUBLE_2ADDR:
-        case OP_DIV_DOUBLE_2ADDR:
-        case OP_REM_DOUBLE_2ADDR:
-        case OP_GOTO_16:
-        case OP_GOTO_32:
-        case OP_CONST_16:
-        case OP_CONST_WIDE_16:
-        case OP_IF_EQZ:
-        case OP_IF_NEZ:
-        case OP_IF_LTZ:
-        case OP_IF_GEZ:
-        case OP_IF_GTZ:
-        case OP_IF_LEZ:
-        case OP_FILL_ARRAY_DATA:
-        case OP_PACKED_SWITCH:
-        case OP_SPARSE_SWITCH:
-        case OP_ADD_INT_LIT8:
-        case OP_RSUB_INT_LIT8:
-        case OP_MUL_INT_LIT8:
-        case OP_DIV_INT_LIT8:
-        case OP_REM_INT_LIT8:
-        case OP_AND_INT_LIT8:
-        case OP_OR_INT_LIT8:
-        case OP_XOR_INT_LIT8:
-        case OP_SHL_INT_LIT8:
-        case OP_SHR_INT_LIT8:
-        case OP_USHR_INT_LIT8:
-        case OP_ADD_INT_LIT16:
-        case OP_RSUB_INT:
-        case OP_MUL_INT_LIT16:
-        case OP_DIV_INT_LIT16:
-        case OP_REM_INT_LIT16:
-        case OP_AND_INT_LIT16:
-        case OP_OR_INT_LIT16:
-        case OP_XOR_INT_LIT16:
-        case OP_IF_EQ:
-        case OP_IF_NE:
-        case OP_IF_LT:
-        case OP_IF_GE:
-        case OP_IF_GT:
-        case OP_IF_LE:
-        case OP_MOVE_FROM16:
-        case OP_MOVE_WIDE_FROM16:
-        case OP_MOVE_OBJECT_FROM16:
-        case OP_CMPL_FLOAT:
-        case OP_CMPG_FLOAT:
-        case OP_CMPL_DOUBLE:
-        case OP_CMPG_DOUBLE:
-        case OP_CMP_LONG:
-        case OP_AGET:
-        case OP_AGET_WIDE:
-        case OP_AGET_OBJECT:
-        case OP_AGET_BOOLEAN:
-        case OP_AGET_BYTE:
-        case OP_AGET_CHAR:
-        case OP_AGET_SHORT:
-        case OP_APUT:
-        case OP_APUT_WIDE:
-        case OP_APUT_OBJECT:
-        case OP_APUT_BOOLEAN:
-        case OP_APUT_BYTE:
-        case OP_APUT_CHAR:
-        case OP_APUT_SHORT:
-        case OP_ADD_INT:
-        case OP_SUB_INT:
-        case OP_MUL_INT:
-        case OP_DIV_INT:
-        case OP_REM_INT:
-        case OP_AND_INT:
-        case OP_OR_INT:
-        case OP_XOR_INT:
-        case OP_SHL_INT:
-        case OP_SHR_INT:
-        case OP_USHR_INT:
-        case OP_ADD_LONG:
-        case OP_SUB_LONG:
-        case OP_MUL_LONG:
-        case OP_DIV_LONG:
-        case OP_REM_LONG:
-        case OP_AND_LONG:
-        case OP_OR_LONG:
-        case OP_XOR_LONG:
-        case OP_SHL_LONG:
-        case OP_SHR_LONG:
-        case OP_USHR_LONG:
-        case OP_ADD_FLOAT:
-        case OP_SUB_FLOAT:
-        case OP_MUL_FLOAT:
-        case OP_DIV_FLOAT:
-        case OP_REM_FLOAT:
-        case OP_ADD_DOUBLE:
-        case OP_SUB_DOUBLE:
-        case OP_MUL_DOUBLE:
-        case OP_DIV_DOUBLE:
-        case OP_REM_DOUBLE:
-        case OP_CONST:
-        case OP_CONST_WIDE_32:
-        case OP_MOVE_16:
-        case OP_MOVE_WIDE_16:
-        case OP_MOVE_OBJECT_16:
-        case OP_CONST_WIDE:
-            indexType = kIndexNone;
-            break;
-        case OP_CONST_STRING:
-        case OP_CONST_STRING_JUMBO:
-            indexType = kIndexStringRef;
-            break;
-        case OP_CONST_CLASS:
-        case OP_CHECK_CAST:
-        case OP_NEW_INSTANCE:
-        case OP_INSTANCE_OF:
-        case OP_NEW_ARRAY:
-        case OP_FILLED_NEW_ARRAY:
-        case OP_FILLED_NEW_ARRAY_RANGE:
-            indexType = kIndexTypeRef;
-            break;
-        case OP_SGET:
-        case OP_SGET_WIDE:
-        case OP_SGET_OBJECT:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BYTE:
-        case OP_SGET_CHAR:
-        case OP_SGET_SHORT:
-        case OP_SPUT:
-        case OP_SPUT_WIDE:
-        case OP_SPUT_OBJECT:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_SHORT:
-        case OP_IGET:
-        case OP_IGET_WIDE:
-        case OP_IGET_OBJECT:
-        case OP_IGET_BOOLEAN:
-        case OP_IGET_BYTE:
-        case OP_IGET_CHAR:
-        case OP_IGET_SHORT:
-        case OP_IPUT:
-        case OP_IPUT_WIDE:
-        case OP_IPUT_OBJECT:
-        case OP_IPUT_BOOLEAN:
-        case OP_IPUT_BYTE:
-        case OP_IPUT_CHAR:
-        case OP_IPUT_SHORT:
-            indexType = kIndexFieldRef;
-            break;
-        case OP_INVOKE_VIRTUAL:
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_INTERFACE:
-        case OP_INVOKE_VIRTUAL_RANGE:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_INTERFACE_RANGE:
-            indexType = kIndexMethodRef;
-            break;
-
-        /*
-         * Optimized instructions.
-         */
-        case OP_THROW_VERIFICATION_ERROR:
-            indexType = kIndexVaries;
-            break;
-        case OP_IGET_WIDE_VOLATILE:
-        case OP_IPUT_WIDE_VOLATILE:
-        case OP_IGET_VOLATILE:
-        case OP_IPUT_VOLATILE:
-        case OP_IGET_OBJECT_VOLATILE:
-        case OP_IPUT_OBJECT_VOLATILE:
-        case OP_SGET_OBJECT_VOLATILE:
-        case OP_SPUT_OBJECT_VOLATILE:
-        case OP_SGET_VOLATILE:
-        case OP_SPUT_VOLATILE:
-        case OP_SGET_WIDE_VOLATILE:
-        case OP_SPUT_WIDE_VOLATILE:
-            indexType = kIndexFieldRef;
-            break;
-        case OP_IGET_QUICK:
-        case OP_IGET_WIDE_QUICK:
-        case OP_IGET_OBJECT_QUICK:
-        case OP_IPUT_QUICK:
-        case OP_IPUT_WIDE_QUICK:
-        case OP_IPUT_OBJECT_QUICK:
-            indexType = kIndexFieldOffset;
-            break;
-        case OP_INVOKE_VIRTUAL_QUICK:
-        case OP_INVOKE_SUPER_QUICK:
-        case OP_INVOKE_VIRTUAL_QUICK_RANGE:
-        case OP_INVOKE_SUPER_QUICK_RANGE:
-            indexType = kIndexVtableOffset;
-            break;
-        case OP_EXECUTE_INLINE:
-        case OP_EXECUTE_INLINE_RANGE:
-            indexType = kIndexInlineMethod;
-            break;
-        case OP_INVOKE_DIRECT_EMPTY:
-            indexType = kIndexMethodRef;
-            break;
-        case OP_RETURN_VOID_BARRIER:
-            indexType = kIndexNone;
-            break;
-
-        /* these should never appear when scanning code */
-        case OP_UNUSED_3E:
-        case OP_UNUSED_3F:
-        case OP_UNUSED_40:
-        case OP_UNUSED_41:
-        case OP_UNUSED_42:
-        case OP_UNUSED_43:
-        case OP_UNUSED_73:
-        case OP_UNUSED_79:
-        case OP_UNUSED_7A:
-        case OP_BREAKPOINT:
-        case OP_UNUSED_FF:
-            indexType = kIndexUnknown;
-            break;
-
-        /*
-         * DO NOT add a "default" clause here.  Without it the compiler will
-         * complain if an instruction is missing (which is desirable).
-         */
-        }
-
-        indexTypes[opc] = indexType;
-    }
-
-    return indexTypes;
-}
-
-/*
- * Construct all of the instruction info tables, storing references to
- * them into the given struct. This returns 0 on success or non-zero on
- * failure. If this fails, then no net allocation will have occurred.
- */
-int dexCreateInstructionInfoTables(InstructionInfoTables* info) {
-    info->formats = NULL;
-    info->indexTypes = NULL;
-    info->flags = NULL;
-    info->widths = NULL;
-
-    info->formats = dexCreateInstrFormatTable();
-    info->indexTypes = dexCreateInstrIndexTypeTable();
-    info->flags = dexCreateInstrFlagsTable();
-    info->widths = dexCreateInstrWidthTable();
-
-    if ((info->formats == NULL)
-            || (info->indexTypes == NULL)
-            || (info->flags == NULL)
-            || (info->widths == NULL)) {
-        dexFreeInstructionInfoTables(info);
-        return 1;
-    }
-
-    return 0;
-}
-
-/*
- * Free up the tables referred to by the given instruction info struct.
- */
-void dexFreeInstructionInfoTables(InstructionInfoTables* info) {
-    free(info->formats);
-    free(info->indexTypes);
-    free(info->flags);
-    free(info->widths);
+void dexGetInstructionInfoTables(InstructionInfoTables* info) {
+    *info = gDexOpcodeInfo;
 }
 
 /*
@@ -1855,15 +496,14 @@
  * Fills out the pieces of "pDec" that are affected by the current
  * instruction.  Does not touch anything else.
  */
-void dexDecodeInstruction(const InstructionInfoTables* info, const u2* insns,
-    DecodedInstruction* pDec)
+void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec)
 {
     u2 inst = *insns;
     OpCode opCode = (OpCode) INST_INST(inst);
-    InstructionFormat format = dexGetInstrFormat(info->formats, opCode);
+    InstructionFormat format = dexGetInstrFormat(gOpcodeFormatTable, opCode);
 
     pDec->opCode = opCode;
-    pDec->indexType = dexGetInstrIndexType(info->indexTypes, opCode);
+    pDec->indexType = dexGetInstrIndexType(gOpcodeIndexTypeTable, opCode);
 
     switch (format) {
     case kFmt10x:       // op
@@ -2062,8 +702,7 @@
  * works for special OP_NOP entries, including switch statement data tables
  * and array data.
  */
-size_t dexGetInstrOrTableWidth(const InstructionWidth* widths,
-    const u2* insns)
+size_t dexGetInstrOrTableWidth(const u2* insns)
 {
     size_t width;
 
@@ -2076,7 +715,7 @@
         u4 len = insns[2] | (((u4)insns[3]) << 16);
         width = 4 + (elemWidth * len + 1) / 2;
     } else {
-        width = dexGetInstrWidth(widths, INST_INST(insns[0]));
+        width = dexGetInstrWidth(gOpcodeWidthTable, INST_INST(insns[0]));
     }
     return width;
 }
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
index 44e5af2..b4678ff 100644
--- a/libdex/InstrUtils.h
+++ b/libdex/InstrUtils.h
@@ -138,10 +138,9 @@
 } InstructionInfoTables;
 
 /*
- * Allocate and populate a 256-element array with instruction widths.  A
- * width of zero means the entry does not exist.
+ * Global InstructionInfoTables struct.
  */
-InstructionWidth* dexCreateInstrWidthTable(void);
+extern InstructionInfoTables gDexOpcodeInfo;
 
 /*
  * Return the width of the specified instruction, or 0 if not defined.
@@ -158,13 +157,7 @@
  * works for special OP_NOP entries, including switch statement data tables
  * and array data.
  */
-size_t dexGetInstrOrTableWidth(const InstructionWidth* widths,
-    const u2* insns);
-
-/*
- * Allocate and populate a 256-element array with instruction flags.
- */
-InstructionFlags* dexCreateInstrFlagsTable(void);
+size_t dexGetInstrOrTableWidth(const u2* insns);
 
 /*
  * Returns the flags for the specified opcode.
@@ -184,11 +177,6 @@
 }
 
 /*
- * Allocate and populate a 256-element array with instruction formats.
- */
-InstructionFormat* dexCreateInstrFormatTable(void);
-
-/*
  * Return the instruction format for the specified opcode.
  */
 DEX_INLINE InstructionFormat dexGetInstrFormat(const InstructionFormat* fmts,
@@ -199,12 +187,6 @@
 }
 
 /*
- * Allocate and populate an array with index types for all instructions.
- * Used in conjunction with dexDecodeInstruction.
- */
-InstructionIndexType* dexCreateInstrIndexTypeTable(void);
-
-/*
  * Return the instruction index type for the specified opcode.
  */
 DEX_INLINE InstructionIndexType dexGetInstrIndexType(
@@ -215,21 +197,14 @@
 }
 
 /*
- * Construct all of the instruction info tables, storing references to
- * them into the given struct. This returns 0 on success or non-zero on
- * failure. If this fails, then no net allocation will have occurred.
+ * Copy pointers to all of the instruction info tables into
+ * the given struct.
  */
-int dexCreateInstructionInfoTables(InstructionInfoTables* info);
-
-/*
- * Free up the tables referred to by the given instruction info struct.
- */
-void dexFreeInstructionInfoTables(InstructionInfoTables* info);
+void dexGetInstructionInfoTables(InstructionInfoTables* info);
 
 /*
  * Decode the instruction pointed to by "insns".
  */
-void dexDecodeInstruction(const InstructionInfoTables* info, const u2* insns,
-    DecodedInstruction* pDec);
+void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec);
 
 #endif /*_LIBDEX_INSTRUTILS*/
diff --git a/libdex/OpCode.h b/libdex/OpCode.h
index 32d3b3e..4c5ae52 100644
--- a/libdex/OpCode.h
+++ b/libdex/OpCode.h
@@ -41,8 +41,8 @@
  *    immediately below in this file.
  *
  * Opcode definitions and attributes:
- *  - update the instruction info table generators and (if you changed an
- *    instruction format) instruction decoder in InstrUtils.c
+ *  - update the instruction decoder in InstrUtils.c if you added a new
+ *    instruction format.
  *  - update the instruction format list in InstrUtils.h, if necessary
  *  - update the parallel definitions in the class dalvik.bytecode.Opcodes
  *
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 2069848..e9ae842 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -3557,7 +3557,7 @@
 #ifndef NDEBUG
     memset(&decInsn, 0x81, sizeof(decInsn));
 #endif
-    dexDecodeInstruction(&gDvm.instrInfo, insns, &decInsn);
+    dexDecodeInstruction(insns, &decInsn);
 
     int nextFlags = dexGetInstrFlags(gDvm.instrInfo.flags, decInsn.opCode);
 
diff --git a/vm/analysis/DexVerify.c b/vm/analysis/DexVerify.c
index b35c4ae..654bd01 100644
--- a/vm/analysis/DexVerify.c
+++ b/vm/analysis/DexVerify.c
@@ -33,11 +33,7 @@
  */
 bool dvmVerificationStartup(void)
 {
-    if (dexCreateInstructionInfoTables(&gDvm.instrInfo)) {
-        LOGE("Unable to create instruction tables\n");
-        return false;
-    }
-
+    dexGetInstructionInfoTables(&gDvm.instrInfo);
     return true;
 }
 
@@ -46,7 +42,7 @@
  */
 void dvmVerificationShutdown(void)
 {
-    dexFreeInstructionInfoTables(&gDvm.instrInfo);
+    /* No need to do anything here. */
 }
 
 /*
@@ -112,7 +108,7 @@
 
 
     for (i = 0; i < (int) insnCount; /**/) {
-        size_t width = dexGetInstrOrTableWidth(gDvm.instrInfo.widths, insns);
+        size_t width = dexGetInstrOrTableWidth(insns);
         if (width == 0) {
             LOG_VFY_METH(meth,
                 "VFY: invalid post-opt instruction (0x%04x)\n", *insns);
@@ -817,7 +813,6 @@
     const Method* meth = vdata->method;
     const DvmDex* pDvmDex = meth->clazz->pDvmDex;
     InsnFlags* insnFlags = vdata->insnFlags;
-    const InstructionInfoTables* infoTables = &gDvm.instrInfo;
     const InstructionFlags* flagTable = gDvm.instrInfo.flags;
     const u2* insns = meth->insns;
     unsigned int codeOffset;
@@ -833,7 +828,7 @@
         DecodedInstruction decInsn;
         bool okay = true;
 
-        dexDecodeInstruction(infoTables, meth->insns + codeOffset, &decInsn);
+        dexDecodeInstruction(meth->insns + codeOffset, &decInsn);
 
         /*
          * Check register, type, class, field, method, and string indices
diff --git a/vm/analysis/Optimize.c b/vm/analysis/Optimize.c
index 6bc221e..5204096 100644
--- a/vm/analysis/Optimize.c
+++ b/vm/analysis/Optimize.c
@@ -299,7 +299,7 @@
             }
         }
 
-        width = dexGetInstrOrTableWidth(gDvm.instrInfo.widths, insns);
+        width = dexGetInstrOrTableWidth(insns);
         assert(width > 0);
 
         insns += width;
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 3c1e837..af704af 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -40,7 +40,7 @@
         }
     }
 
-    dexDecodeInstruction(&gDvm.instrInfo, codePtr, decInsn);
+    dexDecodeInstruction(codePtr, decInsn);
     if (printMe) {
         char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn, NULL);
         LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
diff --git a/vm/compiler/InlineTransformation.c b/vm/compiler/InlineTransformation.c
index 951da61..f93558c 100644
--- a/vm/compiler/InlineTransformation.c
+++ b/vm/compiler/InlineTransformation.c
@@ -46,7 +46,7 @@
     MIR *newGetterMIR = dvmCompilerNew(sizeof(MIR), true);
     DecodedInstruction getterInsn;
 
-    dexDecodeInstruction(&gDvm.instrInfo, calleeMethod->insns, &getterInsn);
+    dexDecodeInstruction(calleeMethod->insns, &getterInsn);
 
     if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &getterInsn))
         return;
@@ -137,7 +137,7 @@
     MIR *newSetterMIR = dvmCompilerNew(sizeof(MIR), true);
     DecodedInstruction setterInsn;
 
-    dexDecodeInstruction(&gDvm.instrInfo, calleeMethod->insns, &setterInsn);
+    dexDecodeInstruction(calleeMethod->insns, &setterInsn);
 
     if (!dvmCompilerCanIncludeThisInstruction(calleeMethod, &setterInsn))
         return;
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index be9d6df..2ae49ca 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -288,7 +288,7 @@
     SelfVerificationState state = shadowSpace->selfVerificationState;
 
     DecodedInstruction decInsn;
-    dexDecodeInstruction(&gDvm.instrInfo, pc, &decInsn);
+    dexDecodeInstruction(pc, &decInsn);
 
     //LOGD("### DbgIntp(%d): PC: 0x%x endPC: 0x%x state: %d len: %d %s",
     //    self->threadId, (int)pc, (int)shadowSpace->endPC, state,
@@ -669,7 +669,7 @@
     DecodedInstruction nextDecInsn;
     const u2 *moveResultPC = lastPC + len;
 
-    dexDecodeInstruction(&gDvm.instrInfo, moveResultPC, &nextDecInsn);
+    dexDecodeInstruction(moveResultPC, &nextDecInsn);
     if ((nextDecInsn.opCode != OP_MOVE_RESULT) &&
         (nextDecInsn.opCode != OP_MOVE_RESULT_WIDE) &&
         (nextDecInsn.opCode != OP_MOVE_RESULT_OBJECT))
@@ -685,8 +685,7 @@
     interpState->trace[currTraceRun].frag.isCode = true;
     interpState->totalTraceLen++;
 
-    interpState->currRunLen = dexGetInstrOrTableWidth(gDvm.instrInfo.widths,
-                                                      moveResultPC);
+    interpState->currRunLen = dexGetInstrOrTableWidth(moveResultPC);
 }
 
 /*
@@ -733,7 +732,7 @@
             /* First instruction - just remember the PC and exit */
             if (lastPC == NULL) break;
             /* Grow the trace around the last PC if jitState is kJitTSelect */
-            dexDecodeInstruction(&gDvm.instrInfo, lastPC, &decInsn);
+            dexDecodeInstruction(lastPC, &decInsn);
 
             /*
              * Treat {PACKED,SPARSE}_SWITCH as trace-ending instructions due
@@ -752,7 +751,7 @@
             LOGD("TraceGen: adding %s", dexGetOpcodeName(decInsn.opCode));
 #endif
             flags = dexGetInstrFlags(gDvm.instrInfo.flags, decInsn.opCode);
-            len = dexGetInstrOrTableWidth(gDvm.instrInfo.widths, lastPC);
+            len = dexGetInstrOrTableWidth(lastPC);
             offset = lastPC - interpState->method->insns;
             assert((unsigned) offset <
                    dvmGetMethodInsnsSize(interpState->method));