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.dex.code; 18 19 import com.android.dx.rop.code.Insn; 20 import com.android.dx.rop.code.RegOps; 21 import com.android.dx.rop.code.RegisterSpec; 22 import com.android.dx.rop.code.Rop; 23 import com.android.dx.rop.code.Rops; 24 import com.android.dx.rop.code.ThrowingCstInsn; 25 import com.android.dx.rop.cst.Constant; 26 import com.android.dx.rop.cst.CstFieldRef; 27 import com.android.dx.rop.cst.CstMethodHandle; 28 import com.android.dx.rop.cst.CstProtoRef; 29 import com.android.dx.rop.cst.CstString; 30 import com.android.dx.rop.cst.CstType; 31 import com.android.dx.rop.type.Type; 32 import java.util.HashMap; 33 34 /** 35 * Translator from rop-level {@link Insn} instances to corresponding 36 * {@link Dop} instances. 37 */ 38 public final class RopToDop { 39 /** {@code non-null;} map from all the common rops to dalvik opcodes */ 40 private static final HashMap<Rop, Dop> MAP; 41 42 /** 43 * This class is uninstantiable. 44 */ RopToDop()45 private RopToDop() { 46 // This space intentionally left blank. 47 } 48 49 /* 50 * The following comment lists each opcode that should be considered 51 * the "head" of an opcode chain, in terms of the process of fitting 52 * an instruction's arguments to an actual opcode. This list is 53 * automatically generated and may be of use in double-checking the 54 * manually-generated static initialization code for this class. 55 * 56 * TODO: Make opcode-gen produce useful code in this case instead 57 * of just a comment. 58 */ 59 60 // BEGIN(first-opcodes); GENERATED AUTOMATICALLY BY opcode-gen 61 // Opcodes.NOP 62 // Opcodes.MOVE 63 // Opcodes.MOVE_WIDE 64 // Opcodes.MOVE_OBJECT 65 // Opcodes.MOVE_RESULT 66 // Opcodes.MOVE_RESULT_WIDE 67 // Opcodes.MOVE_RESULT_OBJECT 68 // Opcodes.MOVE_EXCEPTION 69 // Opcodes.RETURN_VOID 70 // Opcodes.RETURN 71 // Opcodes.RETURN_WIDE 72 // Opcodes.RETURN_OBJECT 73 // Opcodes.CONST_4 74 // Opcodes.CONST_WIDE_16 75 // Opcodes.CONST_STRING 76 // Opcodes.CONST_CLASS 77 // Opcodes.MONITOR_ENTER 78 // Opcodes.MONITOR_EXIT 79 // Opcodes.CHECK_CAST 80 // Opcodes.INSTANCE_OF 81 // Opcodes.ARRAY_LENGTH 82 // Opcodes.NEW_INSTANCE 83 // Opcodes.NEW_ARRAY 84 // Opcodes.FILLED_NEW_ARRAY 85 // Opcodes.FILL_ARRAY_DATA 86 // Opcodes.THROW 87 // Opcodes.GOTO 88 // Opcodes.PACKED_SWITCH 89 // Opcodes.SPARSE_SWITCH 90 // Opcodes.CMPL_FLOAT 91 // Opcodes.CMPG_FLOAT 92 // Opcodes.CMPL_DOUBLE 93 // Opcodes.CMPG_DOUBLE 94 // Opcodes.CMP_LONG 95 // Opcodes.IF_EQ 96 // Opcodes.IF_NE 97 // Opcodes.IF_LT 98 // Opcodes.IF_GE 99 // Opcodes.IF_GT 100 // Opcodes.IF_LE 101 // Opcodes.IF_EQZ 102 // Opcodes.IF_NEZ 103 // Opcodes.IF_LTZ 104 // Opcodes.IF_GEZ 105 // Opcodes.IF_GTZ 106 // Opcodes.IF_LEZ 107 // Opcodes.AGET 108 // Opcodes.AGET_WIDE 109 // Opcodes.AGET_OBJECT 110 // Opcodes.AGET_BOOLEAN 111 // Opcodes.AGET_BYTE 112 // Opcodes.AGET_CHAR 113 // Opcodes.AGET_SHORT 114 // Opcodes.APUT 115 // Opcodes.APUT_WIDE 116 // Opcodes.APUT_OBJECT 117 // Opcodes.APUT_BOOLEAN 118 // Opcodes.APUT_BYTE 119 // Opcodes.APUT_CHAR 120 // Opcodes.APUT_SHORT 121 // Opcodes.IGET 122 // Opcodes.IGET_WIDE 123 // Opcodes.IGET_OBJECT 124 // Opcodes.IGET_BOOLEAN 125 // Opcodes.IGET_BYTE 126 // Opcodes.IGET_CHAR 127 // Opcodes.IGET_SHORT 128 // Opcodes.IPUT 129 // Opcodes.IPUT_WIDE 130 // Opcodes.IPUT_OBJECT 131 // Opcodes.IPUT_BOOLEAN 132 // Opcodes.IPUT_BYTE 133 // Opcodes.IPUT_CHAR 134 // Opcodes.IPUT_SHORT 135 // Opcodes.SGET 136 // Opcodes.SGET_WIDE 137 // Opcodes.SGET_OBJECT 138 // Opcodes.SGET_BOOLEAN 139 // Opcodes.SGET_BYTE 140 // Opcodes.SGET_CHAR 141 // Opcodes.SGET_SHORT 142 // Opcodes.SPUT 143 // Opcodes.SPUT_WIDE 144 // Opcodes.SPUT_OBJECT 145 // Opcodes.SPUT_BOOLEAN 146 // Opcodes.SPUT_BYTE 147 // Opcodes.SPUT_CHAR 148 // Opcodes.SPUT_SHORT 149 // Opcodes.INVOKE_VIRTUAL 150 // Opcodes.INVOKE_SUPER 151 // Opcodes.INVOKE_DIRECT 152 // Opcodes.INVOKE_STATIC 153 // Opcodes.INVOKE_INTERFACE 154 // Opcodes.NEG_INT 155 // Opcodes.NOT_INT 156 // Opcodes.NEG_LONG 157 // Opcodes.NOT_LONG 158 // Opcodes.NEG_FLOAT 159 // Opcodes.NEG_DOUBLE 160 // Opcodes.INT_TO_LONG 161 // Opcodes.INT_TO_FLOAT 162 // Opcodes.INT_TO_DOUBLE 163 // Opcodes.LONG_TO_INT 164 // Opcodes.LONG_TO_FLOAT 165 // Opcodes.LONG_TO_DOUBLE 166 // Opcodes.FLOAT_TO_INT 167 // Opcodes.FLOAT_TO_LONG 168 // Opcodes.FLOAT_TO_DOUBLE 169 // Opcodes.DOUBLE_TO_INT 170 // Opcodes.DOUBLE_TO_LONG 171 // Opcodes.DOUBLE_TO_FLOAT 172 // Opcodes.INT_TO_BYTE 173 // Opcodes.INT_TO_CHAR 174 // Opcodes.INT_TO_SHORT 175 // Opcodes.ADD_INT_2ADDR 176 // Opcodes.SUB_INT_2ADDR 177 // Opcodes.MUL_INT_2ADDR 178 // Opcodes.DIV_INT_2ADDR 179 // Opcodes.REM_INT_2ADDR 180 // Opcodes.AND_INT_2ADDR 181 // Opcodes.OR_INT_2ADDR 182 // Opcodes.XOR_INT_2ADDR 183 // Opcodes.SHL_INT_2ADDR 184 // Opcodes.SHR_INT_2ADDR 185 // Opcodes.USHR_INT_2ADDR 186 // Opcodes.ADD_LONG_2ADDR 187 // Opcodes.SUB_LONG_2ADDR 188 // Opcodes.MUL_LONG_2ADDR 189 // Opcodes.DIV_LONG_2ADDR 190 // Opcodes.REM_LONG_2ADDR 191 // Opcodes.AND_LONG_2ADDR 192 // Opcodes.OR_LONG_2ADDR 193 // Opcodes.XOR_LONG_2ADDR 194 // Opcodes.SHL_LONG_2ADDR 195 // Opcodes.SHR_LONG_2ADDR 196 // Opcodes.USHR_LONG_2ADDR 197 // Opcodes.ADD_FLOAT_2ADDR 198 // Opcodes.SUB_FLOAT_2ADDR 199 // Opcodes.MUL_FLOAT_2ADDR 200 // Opcodes.DIV_FLOAT_2ADDR 201 // Opcodes.REM_FLOAT_2ADDR 202 // Opcodes.ADD_DOUBLE_2ADDR 203 // Opcodes.SUB_DOUBLE_2ADDR 204 // Opcodes.MUL_DOUBLE_2ADDR 205 // Opcodes.DIV_DOUBLE_2ADDR 206 // Opcodes.REM_DOUBLE_2ADDR 207 // Opcodes.ADD_INT_LIT8 208 // Opcodes.RSUB_INT_LIT8 209 // Opcodes.MUL_INT_LIT8 210 // Opcodes.DIV_INT_LIT8 211 // Opcodes.REM_INT_LIT8 212 // Opcodes.AND_INT_LIT8 213 // Opcodes.OR_INT_LIT8 214 // Opcodes.XOR_INT_LIT8 215 // Opcodes.SHL_INT_LIT8 216 // Opcodes.SHR_INT_LIT8 217 // Opcodes.USHR_INT_LIT8 218 // Opcodes.INVOKE_POLYMORPHIC 219 // Opcodes.INVOKE_CUSTOM 220 // Opcodes.CONST_METHOD_HANDLE 221 // Opcodes.CONST_METHOD_TYPE 222 // END(first-opcodes) 223 224 static { 225 /* 226 * Note: The choices made here are to pick the optimistically 227 * smallest Dalvik opcode, and leave it to later processing to 228 * pessimize. See the automatically-generated comment above 229 * for reference. 230 */ 231 MAP = new HashMap<Rop, Dop>(400); MAP.put(Rops.NOP, Dops.NOP)232 MAP.put(Rops.NOP, Dops.NOP); MAP.put(Rops.MOVE_INT, Dops.MOVE)233 MAP.put(Rops.MOVE_INT, Dops.MOVE); MAP.put(Rops.MOVE_LONG, Dops.MOVE_WIDE)234 MAP.put(Rops.MOVE_LONG, Dops.MOVE_WIDE); MAP.put(Rops.MOVE_FLOAT, Dops.MOVE)235 MAP.put(Rops.MOVE_FLOAT, Dops.MOVE); MAP.put(Rops.MOVE_DOUBLE, Dops.MOVE_WIDE)236 MAP.put(Rops.MOVE_DOUBLE, Dops.MOVE_WIDE); MAP.put(Rops.MOVE_OBJECT, Dops.MOVE_OBJECT)237 MAP.put(Rops.MOVE_OBJECT, Dops.MOVE_OBJECT); MAP.put(Rops.MOVE_PARAM_INT, Dops.MOVE)238 MAP.put(Rops.MOVE_PARAM_INT, Dops.MOVE); MAP.put(Rops.MOVE_PARAM_LONG, Dops.MOVE_WIDE)239 MAP.put(Rops.MOVE_PARAM_LONG, Dops.MOVE_WIDE); MAP.put(Rops.MOVE_PARAM_FLOAT, Dops.MOVE)240 MAP.put(Rops.MOVE_PARAM_FLOAT, Dops.MOVE); MAP.put(Rops.MOVE_PARAM_DOUBLE, Dops.MOVE_WIDE)241 MAP.put(Rops.MOVE_PARAM_DOUBLE, Dops.MOVE_WIDE); MAP.put(Rops.MOVE_PARAM_OBJECT, Dops.MOVE_OBJECT)242 MAP.put(Rops.MOVE_PARAM_OBJECT, Dops.MOVE_OBJECT); 243 244 /* 245 * Note: No entry for MOVE_EXCEPTION, since it varies by 246 * exception type. (That is, there is no unique instance to 247 * add to the map.) 248 */ 249 MAP.put(Rops.CONST_INT, Dops.CONST_4)250 MAP.put(Rops.CONST_INT, Dops.CONST_4); MAP.put(Rops.CONST_LONG, Dops.CONST_WIDE_16)251 MAP.put(Rops.CONST_LONG, Dops.CONST_WIDE_16); MAP.put(Rops.CONST_FLOAT, Dops.CONST_4)252 MAP.put(Rops.CONST_FLOAT, Dops.CONST_4); MAP.put(Rops.CONST_DOUBLE, Dops.CONST_WIDE_16)253 MAP.put(Rops.CONST_DOUBLE, Dops.CONST_WIDE_16); 254 255 /* 256 * Note: No entry for CONST_OBJECT, since it needs to turn 257 * into either CONST_STRING or CONST_CLASS. 258 */ 259 260 /* 261 * TODO: I think the only case of this is for null, and 262 * const/4 should cover that. 263 */ MAP.put(Rops.CONST_OBJECT_NOTHROW, Dops.CONST_4)264 MAP.put(Rops.CONST_OBJECT_NOTHROW, Dops.CONST_4); 265 MAP.put(Rops.GOTO, Dops.GOTO)266 MAP.put(Rops.GOTO, Dops.GOTO); MAP.put(Rops.IF_EQZ_INT, Dops.IF_EQZ)267 MAP.put(Rops.IF_EQZ_INT, Dops.IF_EQZ); MAP.put(Rops.IF_NEZ_INT, Dops.IF_NEZ)268 MAP.put(Rops.IF_NEZ_INT, Dops.IF_NEZ); MAP.put(Rops.IF_LTZ_INT, Dops.IF_LTZ)269 MAP.put(Rops.IF_LTZ_INT, Dops.IF_LTZ); MAP.put(Rops.IF_GEZ_INT, Dops.IF_GEZ)270 MAP.put(Rops.IF_GEZ_INT, Dops.IF_GEZ); MAP.put(Rops.IF_LEZ_INT, Dops.IF_LEZ)271 MAP.put(Rops.IF_LEZ_INT, Dops.IF_LEZ); MAP.put(Rops.IF_GTZ_INT, Dops.IF_GTZ)272 MAP.put(Rops.IF_GTZ_INT, Dops.IF_GTZ); MAP.put(Rops.IF_EQZ_OBJECT, Dops.IF_EQZ)273 MAP.put(Rops.IF_EQZ_OBJECT, Dops.IF_EQZ); MAP.put(Rops.IF_NEZ_OBJECT, Dops.IF_NEZ)274 MAP.put(Rops.IF_NEZ_OBJECT, Dops.IF_NEZ); MAP.put(Rops.IF_EQ_INT, Dops.IF_EQ)275 MAP.put(Rops.IF_EQ_INT, Dops.IF_EQ); MAP.put(Rops.IF_NE_INT, Dops.IF_NE)276 MAP.put(Rops.IF_NE_INT, Dops.IF_NE); MAP.put(Rops.IF_LT_INT, Dops.IF_LT)277 MAP.put(Rops.IF_LT_INT, Dops.IF_LT); MAP.put(Rops.IF_GE_INT, Dops.IF_GE)278 MAP.put(Rops.IF_GE_INT, Dops.IF_GE); MAP.put(Rops.IF_LE_INT, Dops.IF_LE)279 MAP.put(Rops.IF_LE_INT, Dops.IF_LE); MAP.put(Rops.IF_GT_INT, Dops.IF_GT)280 MAP.put(Rops.IF_GT_INT, Dops.IF_GT); MAP.put(Rops.IF_EQ_OBJECT, Dops.IF_EQ)281 MAP.put(Rops.IF_EQ_OBJECT, Dops.IF_EQ); MAP.put(Rops.IF_NE_OBJECT, Dops.IF_NE)282 MAP.put(Rops.IF_NE_OBJECT, Dops.IF_NE); MAP.put(Rops.SWITCH, Dops.SPARSE_SWITCH)283 MAP.put(Rops.SWITCH, Dops.SPARSE_SWITCH); MAP.put(Rops.ADD_INT, Dops.ADD_INT_2ADDR)284 MAP.put(Rops.ADD_INT, Dops.ADD_INT_2ADDR); MAP.put(Rops.ADD_LONG, Dops.ADD_LONG_2ADDR)285 MAP.put(Rops.ADD_LONG, Dops.ADD_LONG_2ADDR); MAP.put(Rops.ADD_FLOAT, Dops.ADD_FLOAT_2ADDR)286 MAP.put(Rops.ADD_FLOAT, Dops.ADD_FLOAT_2ADDR); MAP.put(Rops.ADD_DOUBLE, Dops.ADD_DOUBLE_2ADDR)287 MAP.put(Rops.ADD_DOUBLE, Dops.ADD_DOUBLE_2ADDR); MAP.put(Rops.SUB_INT, Dops.SUB_INT_2ADDR)288 MAP.put(Rops.SUB_INT, Dops.SUB_INT_2ADDR); MAP.put(Rops.SUB_LONG, Dops.SUB_LONG_2ADDR)289 MAP.put(Rops.SUB_LONG, Dops.SUB_LONG_2ADDR); MAP.put(Rops.SUB_FLOAT, Dops.SUB_FLOAT_2ADDR)290 MAP.put(Rops.SUB_FLOAT, Dops.SUB_FLOAT_2ADDR); MAP.put(Rops.SUB_DOUBLE, Dops.SUB_DOUBLE_2ADDR)291 MAP.put(Rops.SUB_DOUBLE, Dops.SUB_DOUBLE_2ADDR); MAP.put(Rops.MUL_INT, Dops.MUL_INT_2ADDR)292 MAP.put(Rops.MUL_INT, Dops.MUL_INT_2ADDR); MAP.put(Rops.MUL_LONG, Dops.MUL_LONG_2ADDR)293 MAP.put(Rops.MUL_LONG, Dops.MUL_LONG_2ADDR); MAP.put(Rops.MUL_FLOAT, Dops.MUL_FLOAT_2ADDR)294 MAP.put(Rops.MUL_FLOAT, Dops.MUL_FLOAT_2ADDR); MAP.put(Rops.MUL_DOUBLE, Dops.MUL_DOUBLE_2ADDR)295 MAP.put(Rops.MUL_DOUBLE, Dops.MUL_DOUBLE_2ADDR); MAP.put(Rops.DIV_INT, Dops.DIV_INT_2ADDR)296 MAP.put(Rops.DIV_INT, Dops.DIV_INT_2ADDR); MAP.put(Rops.DIV_LONG, Dops.DIV_LONG_2ADDR)297 MAP.put(Rops.DIV_LONG, Dops.DIV_LONG_2ADDR); MAP.put(Rops.DIV_FLOAT, Dops.DIV_FLOAT_2ADDR)298 MAP.put(Rops.DIV_FLOAT, Dops.DIV_FLOAT_2ADDR); MAP.put(Rops.DIV_DOUBLE, Dops.DIV_DOUBLE_2ADDR)299 MAP.put(Rops.DIV_DOUBLE, Dops.DIV_DOUBLE_2ADDR); MAP.put(Rops.REM_INT, Dops.REM_INT_2ADDR)300 MAP.put(Rops.REM_INT, Dops.REM_INT_2ADDR); MAP.put(Rops.REM_LONG, Dops.REM_LONG_2ADDR)301 MAP.put(Rops.REM_LONG, Dops.REM_LONG_2ADDR); MAP.put(Rops.REM_FLOAT, Dops.REM_FLOAT_2ADDR)302 MAP.put(Rops.REM_FLOAT, Dops.REM_FLOAT_2ADDR); MAP.put(Rops.REM_DOUBLE, Dops.REM_DOUBLE_2ADDR)303 MAP.put(Rops.REM_DOUBLE, Dops.REM_DOUBLE_2ADDR); MAP.put(Rops.NEG_INT, Dops.NEG_INT)304 MAP.put(Rops.NEG_INT, Dops.NEG_INT); MAP.put(Rops.NEG_LONG, Dops.NEG_LONG)305 MAP.put(Rops.NEG_LONG, Dops.NEG_LONG); MAP.put(Rops.NEG_FLOAT, Dops.NEG_FLOAT)306 MAP.put(Rops.NEG_FLOAT, Dops.NEG_FLOAT); MAP.put(Rops.NEG_DOUBLE, Dops.NEG_DOUBLE)307 MAP.put(Rops.NEG_DOUBLE, Dops.NEG_DOUBLE); MAP.put(Rops.AND_INT, Dops.AND_INT_2ADDR)308 MAP.put(Rops.AND_INT, Dops.AND_INT_2ADDR); MAP.put(Rops.AND_LONG, Dops.AND_LONG_2ADDR)309 MAP.put(Rops.AND_LONG, Dops.AND_LONG_2ADDR); MAP.put(Rops.OR_INT, Dops.OR_INT_2ADDR)310 MAP.put(Rops.OR_INT, Dops.OR_INT_2ADDR); MAP.put(Rops.OR_LONG, Dops.OR_LONG_2ADDR)311 MAP.put(Rops.OR_LONG, Dops.OR_LONG_2ADDR); MAP.put(Rops.XOR_INT, Dops.XOR_INT_2ADDR)312 MAP.put(Rops.XOR_INT, Dops.XOR_INT_2ADDR); MAP.put(Rops.XOR_LONG, Dops.XOR_LONG_2ADDR)313 MAP.put(Rops.XOR_LONG, Dops.XOR_LONG_2ADDR); MAP.put(Rops.SHL_INT, Dops.SHL_INT_2ADDR)314 MAP.put(Rops.SHL_INT, Dops.SHL_INT_2ADDR); MAP.put(Rops.SHL_LONG, Dops.SHL_LONG_2ADDR)315 MAP.put(Rops.SHL_LONG, Dops.SHL_LONG_2ADDR); MAP.put(Rops.SHR_INT, Dops.SHR_INT_2ADDR)316 MAP.put(Rops.SHR_INT, Dops.SHR_INT_2ADDR); MAP.put(Rops.SHR_LONG, Dops.SHR_LONG_2ADDR)317 MAP.put(Rops.SHR_LONG, Dops.SHR_LONG_2ADDR); MAP.put(Rops.USHR_INT, Dops.USHR_INT_2ADDR)318 MAP.put(Rops.USHR_INT, Dops.USHR_INT_2ADDR); MAP.put(Rops.USHR_LONG, Dops.USHR_LONG_2ADDR)319 MAP.put(Rops.USHR_LONG, Dops.USHR_LONG_2ADDR); MAP.put(Rops.NOT_INT, Dops.NOT_INT)320 MAP.put(Rops.NOT_INT, Dops.NOT_INT); MAP.put(Rops.NOT_LONG, Dops.NOT_LONG)321 MAP.put(Rops.NOT_LONG, Dops.NOT_LONG); 322 MAP.put(Rops.ADD_CONST_INT, Dops.ADD_INT_LIT8)323 MAP.put(Rops.ADD_CONST_INT, Dops.ADD_INT_LIT8); 324 // Note: No dalvik ops for other types of add_const. 325 MAP.put(Rops.SUB_CONST_INT, Dops.RSUB_INT_LIT8)326 MAP.put(Rops.SUB_CONST_INT, Dops.RSUB_INT_LIT8); 327 /* 328 * Note: No dalvik ops for any type of sub_const; instead 329 * there's a *reverse* sub (constant - reg) for ints only. 330 */ 331 MAP.put(Rops.MUL_CONST_INT, Dops.MUL_INT_LIT8)332 MAP.put(Rops.MUL_CONST_INT, Dops.MUL_INT_LIT8); 333 // Note: No dalvik ops for other types of mul_const. 334 MAP.put(Rops.DIV_CONST_INT, Dops.DIV_INT_LIT8)335 MAP.put(Rops.DIV_CONST_INT, Dops.DIV_INT_LIT8); 336 // Note: No dalvik ops for other types of div_const. 337 MAP.put(Rops.REM_CONST_INT, Dops.REM_INT_LIT8)338 MAP.put(Rops.REM_CONST_INT, Dops.REM_INT_LIT8); 339 // Note: No dalvik ops for other types of rem_const. 340 MAP.put(Rops.AND_CONST_INT, Dops.AND_INT_LIT8)341 MAP.put(Rops.AND_CONST_INT, Dops.AND_INT_LIT8); 342 // Note: No dalvik op for and_const_long. 343 MAP.put(Rops.OR_CONST_INT, Dops.OR_INT_LIT8)344 MAP.put(Rops.OR_CONST_INT, Dops.OR_INT_LIT8); 345 // Note: No dalvik op for or_const_long. 346 MAP.put(Rops.XOR_CONST_INT, Dops.XOR_INT_LIT8)347 MAP.put(Rops.XOR_CONST_INT, Dops.XOR_INT_LIT8); 348 // Note: No dalvik op for xor_const_long. 349 MAP.put(Rops.SHL_CONST_INT, Dops.SHL_INT_LIT8)350 MAP.put(Rops.SHL_CONST_INT, Dops.SHL_INT_LIT8); 351 // Note: No dalvik op for shl_const_long. 352 MAP.put(Rops.SHR_CONST_INT, Dops.SHR_INT_LIT8)353 MAP.put(Rops.SHR_CONST_INT, Dops.SHR_INT_LIT8); 354 // Note: No dalvik op for shr_const_long. 355 MAP.put(Rops.USHR_CONST_INT, Dops.USHR_INT_LIT8)356 MAP.put(Rops.USHR_CONST_INT, Dops.USHR_INT_LIT8); 357 // Note: No dalvik op for shr_const_long. 358 MAP.put(Rops.CMPL_LONG, Dops.CMP_LONG)359 MAP.put(Rops.CMPL_LONG, Dops.CMP_LONG); MAP.put(Rops.CMPL_FLOAT, Dops.CMPL_FLOAT)360 MAP.put(Rops.CMPL_FLOAT, Dops.CMPL_FLOAT); MAP.put(Rops.CMPL_DOUBLE, Dops.CMPL_DOUBLE)361 MAP.put(Rops.CMPL_DOUBLE, Dops.CMPL_DOUBLE); MAP.put(Rops.CMPG_FLOAT, Dops.CMPG_FLOAT)362 MAP.put(Rops.CMPG_FLOAT, Dops.CMPG_FLOAT); MAP.put(Rops.CMPG_DOUBLE, Dops.CMPG_DOUBLE)363 MAP.put(Rops.CMPG_DOUBLE, Dops.CMPG_DOUBLE); MAP.put(Rops.CONV_L2I, Dops.LONG_TO_INT)364 MAP.put(Rops.CONV_L2I, Dops.LONG_TO_INT); MAP.put(Rops.CONV_F2I, Dops.FLOAT_TO_INT)365 MAP.put(Rops.CONV_F2I, Dops.FLOAT_TO_INT); MAP.put(Rops.CONV_D2I, Dops.DOUBLE_TO_INT)366 MAP.put(Rops.CONV_D2I, Dops.DOUBLE_TO_INT); MAP.put(Rops.CONV_I2L, Dops.INT_TO_LONG)367 MAP.put(Rops.CONV_I2L, Dops.INT_TO_LONG); MAP.put(Rops.CONV_F2L, Dops.FLOAT_TO_LONG)368 MAP.put(Rops.CONV_F2L, Dops.FLOAT_TO_LONG); MAP.put(Rops.CONV_D2L, Dops.DOUBLE_TO_LONG)369 MAP.put(Rops.CONV_D2L, Dops.DOUBLE_TO_LONG); MAP.put(Rops.CONV_I2F, Dops.INT_TO_FLOAT)370 MAP.put(Rops.CONV_I2F, Dops.INT_TO_FLOAT); MAP.put(Rops.CONV_L2F, Dops.LONG_TO_FLOAT)371 MAP.put(Rops.CONV_L2F, Dops.LONG_TO_FLOAT); MAP.put(Rops.CONV_D2F, Dops.DOUBLE_TO_FLOAT)372 MAP.put(Rops.CONV_D2F, Dops.DOUBLE_TO_FLOAT); MAP.put(Rops.CONV_I2D, Dops.INT_TO_DOUBLE)373 MAP.put(Rops.CONV_I2D, Dops.INT_TO_DOUBLE); MAP.put(Rops.CONV_L2D, Dops.LONG_TO_DOUBLE)374 MAP.put(Rops.CONV_L2D, Dops.LONG_TO_DOUBLE); MAP.put(Rops.CONV_F2D, Dops.FLOAT_TO_DOUBLE)375 MAP.put(Rops.CONV_F2D, Dops.FLOAT_TO_DOUBLE); MAP.put(Rops.TO_BYTE, Dops.INT_TO_BYTE)376 MAP.put(Rops.TO_BYTE, Dops.INT_TO_BYTE); MAP.put(Rops.TO_CHAR, Dops.INT_TO_CHAR)377 MAP.put(Rops.TO_CHAR, Dops.INT_TO_CHAR); MAP.put(Rops.TO_SHORT, Dops.INT_TO_SHORT)378 MAP.put(Rops.TO_SHORT, Dops.INT_TO_SHORT); MAP.put(Rops.RETURN_VOID, Dops.RETURN_VOID)379 MAP.put(Rops.RETURN_VOID, Dops.RETURN_VOID); MAP.put(Rops.RETURN_INT, Dops.RETURN)380 MAP.put(Rops.RETURN_INT, Dops.RETURN); MAP.put(Rops.RETURN_LONG, Dops.RETURN_WIDE)381 MAP.put(Rops.RETURN_LONG, Dops.RETURN_WIDE); MAP.put(Rops.RETURN_FLOAT, Dops.RETURN)382 MAP.put(Rops.RETURN_FLOAT, Dops.RETURN); MAP.put(Rops.RETURN_DOUBLE, Dops.RETURN_WIDE)383 MAP.put(Rops.RETURN_DOUBLE, Dops.RETURN_WIDE); MAP.put(Rops.RETURN_OBJECT, Dops.RETURN_OBJECT)384 MAP.put(Rops.RETURN_OBJECT, Dops.RETURN_OBJECT); MAP.put(Rops.ARRAY_LENGTH, Dops.ARRAY_LENGTH)385 MAP.put(Rops.ARRAY_LENGTH, Dops.ARRAY_LENGTH); MAP.put(Rops.THROW, Dops.THROW)386 MAP.put(Rops.THROW, Dops.THROW); MAP.put(Rops.MONITOR_ENTER, Dops.MONITOR_ENTER)387 MAP.put(Rops.MONITOR_ENTER, Dops.MONITOR_ENTER); MAP.put(Rops.MONITOR_EXIT, Dops.MONITOR_EXIT)388 MAP.put(Rops.MONITOR_EXIT, Dops.MONITOR_EXIT); MAP.put(Rops.AGET_INT, Dops.AGET)389 MAP.put(Rops.AGET_INT, Dops.AGET); MAP.put(Rops.AGET_LONG, Dops.AGET_WIDE)390 MAP.put(Rops.AGET_LONG, Dops.AGET_WIDE); MAP.put(Rops.AGET_FLOAT, Dops.AGET)391 MAP.put(Rops.AGET_FLOAT, Dops.AGET); MAP.put(Rops.AGET_DOUBLE, Dops.AGET_WIDE)392 MAP.put(Rops.AGET_DOUBLE, Dops.AGET_WIDE); MAP.put(Rops.AGET_OBJECT, Dops.AGET_OBJECT)393 MAP.put(Rops.AGET_OBJECT, Dops.AGET_OBJECT); MAP.put(Rops.AGET_BOOLEAN, Dops.AGET_BOOLEAN)394 MAP.put(Rops.AGET_BOOLEAN, Dops.AGET_BOOLEAN); MAP.put(Rops.AGET_BYTE, Dops.AGET_BYTE)395 MAP.put(Rops.AGET_BYTE, Dops.AGET_BYTE); MAP.put(Rops.AGET_CHAR, Dops.AGET_CHAR)396 MAP.put(Rops.AGET_CHAR, Dops.AGET_CHAR); MAP.put(Rops.AGET_SHORT, Dops.AGET_SHORT)397 MAP.put(Rops.AGET_SHORT, Dops.AGET_SHORT); MAP.put(Rops.APUT_INT, Dops.APUT)398 MAP.put(Rops.APUT_INT, Dops.APUT); MAP.put(Rops.APUT_LONG, Dops.APUT_WIDE)399 MAP.put(Rops.APUT_LONG, Dops.APUT_WIDE); MAP.put(Rops.APUT_FLOAT, Dops.APUT)400 MAP.put(Rops.APUT_FLOAT, Dops.APUT); MAP.put(Rops.APUT_DOUBLE, Dops.APUT_WIDE)401 MAP.put(Rops.APUT_DOUBLE, Dops.APUT_WIDE); MAP.put(Rops.APUT_OBJECT, Dops.APUT_OBJECT)402 MAP.put(Rops.APUT_OBJECT, Dops.APUT_OBJECT); MAP.put(Rops.APUT_BOOLEAN, Dops.APUT_BOOLEAN)403 MAP.put(Rops.APUT_BOOLEAN, Dops.APUT_BOOLEAN); MAP.put(Rops.APUT_BYTE, Dops.APUT_BYTE)404 MAP.put(Rops.APUT_BYTE, Dops.APUT_BYTE); MAP.put(Rops.APUT_CHAR, Dops.APUT_CHAR)405 MAP.put(Rops.APUT_CHAR, Dops.APUT_CHAR); MAP.put(Rops.APUT_SHORT, Dops.APUT_SHORT)406 MAP.put(Rops.APUT_SHORT, Dops.APUT_SHORT); MAP.put(Rops.NEW_INSTANCE, Dops.NEW_INSTANCE)407 MAP.put(Rops.NEW_INSTANCE, Dops.NEW_INSTANCE); MAP.put(Rops.CHECK_CAST, Dops.CHECK_CAST)408 MAP.put(Rops.CHECK_CAST, Dops.CHECK_CAST); MAP.put(Rops.INSTANCE_OF, Dops.INSTANCE_OF)409 MAP.put(Rops.INSTANCE_OF, Dops.INSTANCE_OF); 410 MAP.put(Rops.GET_FIELD_LONG, Dops.IGET_WIDE)411 MAP.put(Rops.GET_FIELD_LONG, Dops.IGET_WIDE); MAP.put(Rops.GET_FIELD_FLOAT, Dops.IGET)412 MAP.put(Rops.GET_FIELD_FLOAT, Dops.IGET); MAP.put(Rops.GET_FIELD_DOUBLE, Dops.IGET_WIDE)413 MAP.put(Rops.GET_FIELD_DOUBLE, Dops.IGET_WIDE); MAP.put(Rops.GET_FIELD_OBJECT, Dops.IGET_OBJECT)414 MAP.put(Rops.GET_FIELD_OBJECT, Dops.IGET_OBJECT); 415 /* 416 * Note: No map entries for get_field_* for non-long integral types, 417 * since they need to be handled specially (see dopFor() below). 418 */ 419 MAP.put(Rops.GET_STATIC_LONG, Dops.SGET_WIDE)420 MAP.put(Rops.GET_STATIC_LONG, Dops.SGET_WIDE); MAP.put(Rops.GET_STATIC_FLOAT, Dops.SGET)421 MAP.put(Rops.GET_STATIC_FLOAT, Dops.SGET); MAP.put(Rops.GET_STATIC_DOUBLE, Dops.SGET_WIDE)422 MAP.put(Rops.GET_STATIC_DOUBLE, Dops.SGET_WIDE); MAP.put(Rops.GET_STATIC_OBJECT, Dops.SGET_OBJECT)423 MAP.put(Rops.GET_STATIC_OBJECT, Dops.SGET_OBJECT); 424 /* 425 * Note: No map entries for get_static* for non-long integral types, 426 * since they need to be handled specially (see dopFor() below). 427 */ 428 MAP.put(Rops.PUT_FIELD_LONG, Dops.IPUT_WIDE)429 MAP.put(Rops.PUT_FIELD_LONG, Dops.IPUT_WIDE); MAP.put(Rops.PUT_FIELD_FLOAT, Dops.IPUT)430 MAP.put(Rops.PUT_FIELD_FLOAT, Dops.IPUT); MAP.put(Rops.PUT_FIELD_DOUBLE, Dops.IPUT_WIDE)431 MAP.put(Rops.PUT_FIELD_DOUBLE, Dops.IPUT_WIDE); MAP.put(Rops.PUT_FIELD_OBJECT, Dops.IPUT_OBJECT)432 MAP.put(Rops.PUT_FIELD_OBJECT, Dops.IPUT_OBJECT); 433 /* 434 * Note: No map entries for put_field_* for non-long integral types, 435 * since they need to be handled specially (see dopFor() below). 436 */ 437 MAP.put(Rops.PUT_STATIC_LONG, Dops.SPUT_WIDE)438 MAP.put(Rops.PUT_STATIC_LONG, Dops.SPUT_WIDE); MAP.put(Rops.PUT_STATIC_FLOAT, Dops.SPUT)439 MAP.put(Rops.PUT_STATIC_FLOAT, Dops.SPUT); MAP.put(Rops.PUT_STATIC_DOUBLE, Dops.SPUT_WIDE)440 MAP.put(Rops.PUT_STATIC_DOUBLE, Dops.SPUT_WIDE); MAP.put(Rops.PUT_STATIC_OBJECT, Dops.SPUT_OBJECT)441 MAP.put(Rops.PUT_STATIC_OBJECT, Dops.SPUT_OBJECT); 442 /* 443 * Note: No map entries for put_static* for non-long integral types, 444 * since they need to be handled specially (see dopFor() below). 445 */ 446 447 /* 448 * Note: No map entries for invoke*, new_array, and 449 * filled_new_array, since they need to be handled specially 450 * (see dopFor() below). 451 */ 452 } 453 454 /** 455 * Returns the dalvik opcode appropriate for the given register-based 456 * instruction. 457 * 458 * @param insn {@code non-null;} the original instruction 459 * @return the corresponding dalvik opcode; one of the constants in 460 * {@link Dops} 461 */ dopFor(Insn insn)462 public static Dop dopFor(Insn insn) { 463 Rop rop = insn.getOpcode(); 464 465 /* 466 * First, just try looking up the rop in the MAP of easy 467 * cases. 468 */ 469 Dop result = MAP.get(rop); 470 if (result != null) { 471 return result; 472 } 473 474 /* 475 * There was no easy case for the rop, so look up the opcode, and 476 * do something special for each: 477 * 478 * The move_exception, new_array, filled_new_array, and 479 * invoke* opcodes won't be found in MAP, since they'll each 480 * have different source and/or result register types / lists. 481 * 482 * The get* and put* opcodes for (non-long) integral types 483 * aren't in the map, since the type signatures aren't 484 * sufficient to distinguish between the types (the salient 485 * source or result will always be just "int"). 486 * 487 * And const instruction need to distinguish between strings and 488 * classes. 489 */ 490 491 switch (rop.getOpcode()) { 492 case RegOps.MOVE_EXCEPTION: return Dops.MOVE_EXCEPTION; 493 case RegOps.INVOKE_STATIC: return Dops.INVOKE_STATIC; 494 case RegOps.INVOKE_VIRTUAL: return Dops.INVOKE_VIRTUAL; 495 case RegOps.INVOKE_SUPER: return Dops.INVOKE_SUPER; 496 case RegOps.INVOKE_DIRECT: return Dops.INVOKE_DIRECT; 497 case RegOps.INVOKE_INTERFACE: return Dops.INVOKE_INTERFACE; 498 case RegOps.INVOKE_POLYMORPHIC: return Dops.INVOKE_POLYMORPHIC; 499 case RegOps.INVOKE_CUSTOM: return Dops.INVOKE_CUSTOM; 500 case RegOps.NEW_ARRAY: return Dops.NEW_ARRAY; 501 case RegOps.FILLED_NEW_ARRAY: return Dops.FILLED_NEW_ARRAY; 502 case RegOps.FILL_ARRAY_DATA: return Dops.FILL_ARRAY_DATA; 503 case RegOps.MOVE_RESULT: { 504 RegisterSpec resultReg = insn.getResult(); 505 506 if (resultReg == null) { 507 return Dops.NOP; 508 } else { 509 switch (resultReg.getBasicType()) { 510 case Type.BT_INT: 511 case Type.BT_FLOAT: 512 case Type.BT_BOOLEAN: 513 case Type.BT_BYTE: 514 case Type.BT_CHAR: 515 case Type.BT_SHORT: 516 return Dops.MOVE_RESULT; 517 case Type.BT_LONG: 518 case Type.BT_DOUBLE: 519 return Dops.MOVE_RESULT_WIDE; 520 case Type.BT_OBJECT: 521 return Dops.MOVE_RESULT_OBJECT; 522 default: { 523 throw new RuntimeException("Unexpected basic type"); 524 } 525 } 526 } 527 } 528 529 case RegOps.GET_FIELD: { 530 CstFieldRef ref = 531 (CstFieldRef) ((ThrowingCstInsn) insn).getConstant(); 532 int basicType = ref.getBasicType(); 533 switch (basicType) { 534 case Type.BT_BOOLEAN: return Dops.IGET_BOOLEAN; 535 case Type.BT_BYTE: return Dops.IGET_BYTE; 536 case Type.BT_CHAR: return Dops.IGET_CHAR; 537 case Type.BT_SHORT: return Dops.IGET_SHORT; 538 case Type.BT_INT: return Dops.IGET; 539 } 540 break; 541 } 542 case RegOps.PUT_FIELD: { 543 CstFieldRef ref = 544 (CstFieldRef) ((ThrowingCstInsn) insn).getConstant(); 545 int basicType = ref.getBasicType(); 546 switch (basicType) { 547 case Type.BT_BOOLEAN: return Dops.IPUT_BOOLEAN; 548 case Type.BT_BYTE: return Dops.IPUT_BYTE; 549 case Type.BT_CHAR: return Dops.IPUT_CHAR; 550 case Type.BT_SHORT: return Dops.IPUT_SHORT; 551 case Type.BT_INT: return Dops.IPUT; 552 } 553 break; 554 } 555 case RegOps.GET_STATIC: { 556 CstFieldRef ref = 557 (CstFieldRef) ((ThrowingCstInsn) insn).getConstant(); 558 int basicType = ref.getBasicType(); 559 switch (basicType) { 560 case Type.BT_BOOLEAN: return Dops.SGET_BOOLEAN; 561 case Type.BT_BYTE: return Dops.SGET_BYTE; 562 case Type.BT_CHAR: return Dops.SGET_CHAR; 563 case Type.BT_SHORT: return Dops.SGET_SHORT; 564 case Type.BT_INT: return Dops.SGET; 565 } 566 break; 567 } 568 case RegOps.PUT_STATIC: { 569 CstFieldRef ref = 570 (CstFieldRef) ((ThrowingCstInsn) insn).getConstant(); 571 int basicType = ref.getBasicType(); 572 switch (basicType) { 573 case Type.BT_BOOLEAN: return Dops.SPUT_BOOLEAN; 574 case Type.BT_BYTE: return Dops.SPUT_BYTE; 575 case Type.BT_CHAR: return Dops.SPUT_CHAR; 576 case Type.BT_SHORT: return Dops.SPUT_SHORT; 577 case Type.BT_INT: return Dops.SPUT; 578 } 579 break; 580 } 581 case RegOps.CONST: { 582 Constant cst = ((ThrowingCstInsn) insn).getConstant(); 583 if (cst instanceof CstType) { 584 return Dops.CONST_CLASS; 585 } else if (cst instanceof CstString) { 586 return Dops.CONST_STRING; 587 } else if (cst instanceof CstMethodHandle) { 588 return Dops.CONST_METHOD_HANDLE; 589 } else if (cst instanceof CstProtoRef) { 590 return Dops.CONST_METHOD_TYPE; 591 } else { 592 throw new RuntimeException("Unexpected constant type"); 593 } 594 } 595 } 596 597 throw new RuntimeException("unknown rop: " + rop); 598 } 599 } 600