public static Dop dopFor(Insn insn) {
    Rop rop = insn.getOpcode();

    /*
     * First, just try looking up the rop in the MAP of easy
     * cases.
     */
    Dop result = MAP.get(rop);
    if (result != null) {
      return result;
    }

    /*
     * There was no easy case for the rop, so look up the opcode, and
     * do something special for each:
     *
     * The move_exception, new_array, filled_new_array, and
     * invoke* opcodes won't be found in MAP, since they'll each
     * have different source and/or result register types / lists.
     *
     * The get* and put* opcodes for (non-long) integral types
     * aren't in the map, since the type signatures aren't
     * sufficient to distinguish between the types (the salient
     * source or result will always be just "int").
     *
     * And const instruction need to distinguish between strings and
     * classes.
     */

    switch (rop.getOpcode()) {
      case RegOps.MOVE_EXCEPTION:
        return Dops.MOVE_EXCEPTION;
      case RegOps.INVOKE_STATIC:
        return Dops.INVOKE_STATIC;
      case RegOps.INVOKE_VIRTUAL:
        return Dops.INVOKE_VIRTUAL;
      case RegOps.INVOKE_SUPER:
        return Dops.INVOKE_SUPER;
      case RegOps.INVOKE_DIRECT:
        return Dops.INVOKE_DIRECT;
      case RegOps.INVOKE_INTERFACE:
        return Dops.INVOKE_INTERFACE;
      case RegOps.INVOKE_POLYMORPHIC:
        return Dops.INVOKE_POLYMORPHIC;
      case RegOps.INVOKE_CUSTOM:
        return Dops.INVOKE_CUSTOM;
      case RegOps.NEW_ARRAY:
        return Dops.NEW_ARRAY;
      case RegOps.FILLED_NEW_ARRAY:
        return Dops.FILLED_NEW_ARRAY;
      case RegOps.FILL_ARRAY_DATA:
        return Dops.FILL_ARRAY_DATA;
      case RegOps.MOVE_RESULT:
        {
          RegisterSpec resultReg = insn.getResult();

          if (resultReg == null) {
            return Dops.NOP;
          } else {
            switch (resultReg.getBasicType()) {
              case Type.BT_INT:
              case Type.BT_FLOAT:
              case Type.BT_BOOLEAN:
              case Type.BT_BYTE:
              case Type.BT_CHAR:
              case Type.BT_SHORT:
                return Dops.MOVE_RESULT;
              case Type.BT_LONG:
              case Type.BT_DOUBLE:
                return Dops.MOVE_RESULT_WIDE;
              case Type.BT_OBJECT:
                return Dops.MOVE_RESULT_OBJECT;
              default:
                {
                  throw new RuntimeException("Unexpected basic type");
                }
            }
          }
        }

      case RegOps.GET_FIELD:
        {
          CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
          int basicType = ref.getBasicType();
          switch (basicType) {
            case Type.BT_BOOLEAN:
              return Dops.IGET_BOOLEAN;
            case Type.BT_BYTE:
              return Dops.IGET_BYTE;
            case Type.BT_CHAR:
              return Dops.IGET_CHAR;
            case Type.BT_SHORT:
              return Dops.IGET_SHORT;
            case Type.BT_INT:
              return Dops.IGET;
          }
          break;
        }
      case RegOps.PUT_FIELD:
        {
          CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
          int basicType = ref.getBasicType();
          switch (basicType) {
            case Type.BT_BOOLEAN:
              return Dops.IPUT_BOOLEAN;
            case Type.BT_BYTE:
              return Dops.IPUT_BYTE;
            case Type.BT_CHAR:
              return Dops.IPUT_CHAR;
            case Type.BT_SHORT:
              return Dops.IPUT_SHORT;
            case Type.BT_INT:
              return Dops.IPUT;
          }
          break;
        }
      case RegOps.GET_STATIC:
        {
          CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
          int basicType = ref.getBasicType();
          switch (basicType) {
            case Type.BT_BOOLEAN:
              return Dops.SGET_BOOLEAN;
            case Type.BT_BYTE:
              return Dops.SGET_BYTE;
            case Type.BT_CHAR:
              return Dops.SGET_CHAR;
            case Type.BT_SHORT:
              return Dops.SGET_SHORT;
            case Type.BT_INT:
              return Dops.SGET;
          }
          break;
        }
      case RegOps.PUT_STATIC:
        {
          CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
          int basicType = ref.getBasicType();
          switch (basicType) {
            case Type.BT_BOOLEAN:
              return Dops.SPUT_BOOLEAN;
            case Type.BT_BYTE:
              return Dops.SPUT_BYTE;
            case Type.BT_CHAR:
              return Dops.SPUT_CHAR;
            case Type.BT_SHORT:
              return Dops.SPUT_SHORT;
            case Type.BT_INT:
              return Dops.SPUT;
          }
          break;
        }
      case RegOps.CONST:
        {
          Constant cst = ((ThrowingCstInsn) insn).getConstant();
          if (cst instanceof CstType) {
            return Dops.CONST_CLASS;
          } else if (cst instanceof CstString) {
            return Dops.CONST_STRING;
          } else if (cst instanceof CstMethodHandle) {
            return Dops.CONST_METHOD_HANDLE;
          } else if (cst instanceof CstProtoRef) {
            return Dops.CONST_METHOD_TYPE;
          } else {
            throw new RuntimeException("Unexpected constant type");
          }
        }
    }

    throw new RuntimeException("unknown rop: " + rop);
  }
Returns the dalvik opcode appropriate for the given register-based instruction.

@param insn {@code non-null;} the original instruction
@return the corresponding dalvik opcode; one of the constants in {@link Dops}
android/android_framework/dex-maker/src/main/java/com/android/dx/dex/code/RopToDop.java