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