Home | History | Annotate | Download | only in code
      1 /*
      2  * Copyright (C) 2007 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  */
     16 
     17 package com.android.dx.rop.code;
     18 
     19 import com.android.dx.util.Hex;
     20 
     21 /**
     22  * All the register-based opcodes, and related utilities.
     23  *
     24  * <p><b>Note:</b> Opcode descriptions use a rough pseudocode. {@code r}
     25  * is the result register, {@code x} is the first argument,
     26  * {@code y} is the second argument, and {@code z} is the
     27  * third argument. The expression which describes
     28  * the operation uses Java-ish syntax but is preceded by type indicators for
     29  * each of the values.
     30  */
     31 public final class RegOps {
     32     /** {@code nop()} */
     33     public static final int NOP = 1;
     34 
     35     /** {@code T: any type; r,x: T :: r = x;} */
     36     public static final int MOVE = 2;
     37 
     38     /** {@code T: any type; r,param(x): T :: r = param(x)} */
     39     public static final int MOVE_PARAM = 3;
     40 
     41     /**
     42      * {@code T: Throwable; r: T :: r = caught_exception}.
     43      * <b>Note:</b> This opcode should only ever be used in the
     44      * first instruction of a block, and such blocks must be
     45      * the start of an exception handler.
     46      */
     47     public static final int MOVE_EXCEPTION = 4;
     48 
     49     /** {@code T: any type; r, literal: T :: r = literal;} */
     50     public static final int CONST = 5;
     51 
     52     /** {@code goto label} */
     53     public static final int GOTO = 6;
     54 
     55     /**
     56      * {@code T: int or Object; x,y: T :: if (x == y) goto
     57      * label}
     58      */
     59     public static final int IF_EQ = 7;
     60 
     61     /**
     62      * {@code T: int or Object; x,y: T :: if (x != y) goto
     63      * label}
     64      */
     65     public static final int IF_NE = 8;
     66 
     67     /** {@code x,y: int :: if (x < y) goto label} */
     68     public static final int IF_LT = 9;
     69 
     70     /** {@code x,y: int :: if (x >= y) goto label} */
     71     public static final int IF_GE = 10;
     72 
     73     /** {@code x,y: int :: if (x <= y) goto label} */
     74     public static final int IF_LE = 11;
     75 
     76     /** {@code x,y: int :: if (x > y) goto label} */
     77     public static final int IF_GT = 12;
     78 
     79     /** {@code x: int :: goto table[x]} */
     80     public static final int SWITCH = 13;
     81 
     82     /** {@code T: any numeric type; r,x,y: T :: r = x + y} */
     83     public static final int ADD = 14;
     84 
     85     /** {@code T: any numeric type; r,x,y: T :: r = x - y} */
     86     public static final int SUB = 15;
     87 
     88     /** {@code T: any numeric type; r,x,y: T :: r = x * y} */
     89     public static final int MUL = 16;
     90 
     91     /** {@code T: any numeric type; r,x,y: T :: r = x / y} */
     92     public static final int DIV = 17;
     93 
     94     /**
     95      * {@code T: any numeric type; r,x,y: T :: r = x % y}
     96      * (Java-style remainder)
     97      */
     98     public static final int REM = 18;
     99 
    100     /** {@code T: any numeric type; r,x: T :: r = -x} */
    101     public static final int NEG = 19;
    102 
    103     /** {@code T: any integral type; r,x,y: T :: r = x & y} */
    104     public static final int AND = 20;
    105 
    106     /** {@code T: any integral type; r,x,y: T :: r = x | y} */
    107     public static final int OR = 21;
    108 
    109     /** {@code T: any integral type; r,x,y: T :: r = x ^ y} */
    110     public static final int XOR = 22;
    111 
    112     /**
    113      * {@code T: any integral type; r,x: T; y: int :: r = x << y}
    114      */
    115     public static final int SHL = 23;
    116 
    117     /**
    118      * {@code T: any integral type; r,x: T; y: int :: r = x >> y}
    119      * (signed right-shift)
    120      */
    121     public static final int SHR = 24;
    122 
    123     /**
    124      * {@code T: any integral type; r,x: T; y: int :: r = x >>> y}
    125      * (unsigned right-shift)
    126      */
    127     public static final int USHR = 25;
    128 
    129     /** {@code T: any integral type; r,x: T :: r = ~x} */
    130     public static final int NOT = 26;
    131 
    132     /**
    133      * {@code T: any numeric type; r: int; x,y: T :: r = (x == y) ? 0
    134      * : (x > y) ? 1 : -1} (Java-style "cmpl" where a NaN is
    135      * considered "less than" all other values; also used for integral
    136      * comparisons)
    137      */
    138     public static final int CMPL = 27;
    139 
    140     /**
    141      * {@code T: any floating point type; r: int; x,y: T :: r = (x == y) ? 0
    142      * : (x < y) ? -1 : 1} (Java-style "cmpg" where a NaN is
    143      * considered "greater than" all other values)
    144      */
    145     public static final int CMPG = 28;
    146 
    147     /**
    148      * {@code T: any numeric type; U: any numeric type; r: T; x: U ::
    149      * r = (T) x} (numeric type conversion between the four
    150      * "real" numeric types)
    151      */
    152     public static final int CONV = 29;
    153 
    154     /**
    155      * {@code r,x: int :: r = (x << 24) >> 24} (Java-style
    156      * convert int to byte)
    157      */
    158     public static final int TO_BYTE = 30;
    159 
    160     /**
    161      * {@code r,x: int :: r = x & 0xffff} (Java-style convert int to char)
    162      */
    163     public static final int TO_CHAR = 31;
    164 
    165     /**
    166      * {@code r,x: int :: r = (x << 16) >> 16} (Java-style
    167      * convert int to short)
    168      */
    169     public static final int TO_SHORT = 32;
    170 
    171     /** {@code T: return type for the method; x: T; return x} */
    172     public static final int RETURN = 33;
    173 
    174     /** {@code T: any type; r: int; x: T[]; :: r = x.length} */
    175     public static final int ARRAY_LENGTH = 34;
    176 
    177     /** {@code x: Throwable :: throw(x)} */
    178     public static final int THROW = 35;
    179 
    180     /** {@code x: Object :: monitorenter(x)} */
    181     public static final int MONITOR_ENTER = 36;
    182 
    183     /** {@code x: Object :: monitorexit(x)} */
    184     public static final int MONITOR_EXIT = 37;
    185 
    186     /** {@code T: any type; r: T; x: T[]; y: int :: r = x[y]} */
    187     public static final int AGET = 38;
    188 
    189     /** {@code T: any type; x: T; y: T[]; z: int :: x[y] = z} */
    190     public static final int APUT = 39;
    191 
    192     /**
    193      * {@code T: any non-array object type :: r =
    194      * alloc(T)} (allocate heap space for an object)
    195      */
    196     public static final int NEW_INSTANCE = 40;
    197 
    198     /** {@code T: any array type; r: T; x: int :: r = new T[x]} */
    199     public static final int NEW_ARRAY = 41;
    200 
    201     /**
    202      * {@code T: any array type; r: T; x: int; v0..vx: T :: r = new T[x]
    203      * {v0, ..., vx}}
    204      */
    205     public static final int FILLED_NEW_ARRAY = 42;
    206 
    207     /**
    208      * {@code T: any object type; x: Object :: (T) x} (can
    209      * throw {@code ClassCastException})
    210      */
    211     public static final int CHECK_CAST = 43;
    212 
    213     /**
    214      * {@code T: any object type; x: Object :: x instanceof T}
    215      */
    216     public static final int INSTANCE_OF = 44;
    217 
    218     /**
    219      * {@code T: any type; r: T; x: Object; f: instance field spec of
    220      * type T :: r = x.f}
    221      */
    222     public static final int GET_FIELD = 45;
    223 
    224     /**
    225      * {@code T: any type; r: T; f: static field spec of type T :: r =
    226      * f}
    227      */
    228     public static final int GET_STATIC = 46;
    229 
    230     /**
    231      * {@code T: any type; x: T; y: Object; f: instance field spec of type
    232      * T :: y.f = x}
    233      */
    234     public static final int PUT_FIELD = 47;
    235 
    236     /**
    237      * {@code T: any type; f: static field spec of type T; x: T :: f = x}
    238      */
    239     public static final int PUT_STATIC = 48;
    240 
    241     /**
    242      * {@code Tr, T0, T1...: any types; r: Tr; m: static method spec;
    243      * y0: T0; y1: T1 ... :: r = m(y0, y1, ...)} (call static
    244      * method)
    245      */
    246     public static final int INVOKE_STATIC = 49;
    247 
    248     /**
    249      * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
    250      * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call normal
    251      * virtual method)
    252      */
    253     public static final int INVOKE_VIRTUAL = 50;
    254 
    255     /**
    256      * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
    257      * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call
    258      * superclass virtual method)
    259      */
    260     public static final int INVOKE_SUPER = 51;
    261 
    262     /**
    263      * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
    264      * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call
    265      * direct/special method)
    266      */
    267     public static final int INVOKE_DIRECT = 52;
    268 
    269     /**
    270      * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: interface
    271      * (instance) method spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1,
    272      * ...)} (call interface method)
    273      */
    274     public static final int INVOKE_INTERFACE = 53;
    275 
    276     /**
    277      * {@code T0: any type; name: local variable name  :: mark(name,T0)}
    278      * (mark beginning or end of local variable name)
    279      */
    280     public static final int MARK_LOCAL = 54;
    281 
    282     /**
    283      * {@code T: Any type; r: T :: r = return_type}.
    284      * <b>Note:</b> This opcode should only ever be used in the
    285      * first instruction of a block following an invoke-*.
    286      */
    287     public static final int MOVE_RESULT = 55;
    288 
    289     /**
    290      * {@code T: Any type; r: T :: r = return_type}.
    291      * <b>Note:</b> This opcode should only ever be used in the
    292      * first instruction of a block following a non-invoke throwing insn
    293      */
    294     public static final int MOVE_RESULT_PSEUDO = 56;
    295 
    296     /** {@code T: Any primitive type; v0..vx: T :: {v0, ..., vx}} */
    297     public static final int FILL_ARRAY_DATA = 57;
    298 
    299     /**
    300      * {@code Tr, T0, T1...: any types; r: Tr; x: java.lang.invoke.MethodHandle;
    301      * m: signature polymorphic method
    302      * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call signature
    303      * polymorphic method)
    304      */
    305     public static final int INVOKE_POLYMORPHIC = 58;
    306 
    307     /**
    308      * {@Code Tr, T0, T1...: any types; r: Tr; m: method spec;
    309      * y0: T0; y1: T1 ... :: r = m(y0, y1, ...)
    310      * <b>Note:</b> The signature of the invoked target is determined by the
    311      * dynamic invocation call site information.
    312      */
    313     public static final int INVOKE_CUSTOM = 59;
    314 
    315     /**
    316      * This class is uninstantiable.
    317      */
    318     private RegOps() {
    319         // This space intentionally left blank.
    320     }
    321 
    322     /**
    323      * Gets the name of the given opcode.
    324      *
    325      * @param opcode the opcode
    326      * @return {@code non-null;} its name
    327      */
    328     public static String opName(int opcode) {
    329         switch (opcode) {
    330             case NOP: return "nop";
    331             case MOVE: return "move";
    332             case MOVE_PARAM: return "move-param";
    333             case MOVE_EXCEPTION: return "move-exception";
    334             case CONST: return "const";
    335             case GOTO: return "goto";
    336             case IF_EQ: return "if-eq";
    337             case IF_NE: return "if-ne";
    338             case IF_LT: return "if-lt";
    339             case IF_GE: return "if-ge";
    340             case IF_LE: return "if-le";
    341             case IF_GT: return "if-gt";
    342             case SWITCH: return "switch";
    343             case ADD: return "add";
    344             case SUB: return "sub";
    345             case MUL: return "mul";
    346             case DIV: return "div";
    347             case REM: return "rem";
    348             case NEG: return "neg";
    349             case AND: return "and";
    350             case OR: return "or";
    351             case XOR: return "xor";
    352             case SHL: return "shl";
    353             case SHR: return "shr";
    354             case USHR: return "ushr";
    355             case NOT: return "not";
    356             case CMPL: return "cmpl";
    357             case CMPG: return "cmpg";
    358             case CONV: return "conv";
    359             case TO_BYTE: return "to-byte";
    360             case TO_CHAR: return "to-char";
    361             case TO_SHORT: return "to-short";
    362             case RETURN: return "return";
    363             case ARRAY_LENGTH: return "array-length";
    364             case THROW: return "throw";
    365             case MONITOR_ENTER: return "monitor-enter";
    366             case MONITOR_EXIT: return "monitor-exit";
    367             case AGET: return "aget";
    368             case APUT: return "aput";
    369             case NEW_INSTANCE: return "new-instance";
    370             case NEW_ARRAY: return "new-array";
    371             case FILLED_NEW_ARRAY: return "filled-new-array";
    372             case CHECK_CAST: return "check-cast";
    373             case INSTANCE_OF: return "instance-of";
    374             case GET_FIELD: return "get-field";
    375             case GET_STATIC: return "get-static";
    376             case PUT_FIELD: return "put-field";
    377             case PUT_STATIC: return "put-static";
    378             case INVOKE_STATIC: return "invoke-static";
    379             case INVOKE_VIRTUAL: return "invoke-virtual";
    380             case INVOKE_SUPER: return "invoke-super";
    381             case INVOKE_DIRECT: return "invoke-direct";
    382             case INVOKE_INTERFACE: return "invoke-interface";
    383             case MOVE_RESULT: return "move-result";
    384             case MOVE_RESULT_PSEUDO: return "move-result-pseudo";
    385             case FILL_ARRAY_DATA: return "fill-array-data";
    386             case INVOKE_POLYMORPHIC: return "invoke-polymorphic";
    387             case INVOKE_CUSTOM: return "invoke-custom";
    388         }
    389 
    390         return "unknown-" + Hex.u1(opcode);
    391     }
    392 
    393     /**
    394      * Given an IF_* RegOp, returns the right-to-left flipped version. For
    395      * example, IF_GT becomes IF_LT.
    396      *
    397      * @param opcode An IF_* RegOp
    398      * @return flipped IF Regop
    399      */
    400     public static int flippedIfOpcode(final int opcode) {
    401         switch (opcode) {
    402             case RegOps.IF_EQ:
    403             case RegOps.IF_NE:
    404                 return opcode;
    405             case RegOps.IF_LT:
    406                 return RegOps.IF_GT;
    407             case RegOps.IF_GE:
    408                 return RegOps.IF_LE;
    409             case RegOps.IF_LE:
    410                 return RegOps.IF_GE;
    411             case RegOps.IF_GT:
    412                 return RegOps.IF_LT;
    413             default:
    414                 throw new RuntimeException("Unrecognized IF regop: " + opcode);
    415         }
    416     }
    417 }
    418