1 /* 2 * Copyright (C) 2011 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 #ifndef ART_RUNTIME_DEX_INSTRUCTION_H_ 18 #define ART_RUNTIME_DEX_INSTRUCTION_H_ 19 20 #include "base/logging.h" 21 #include "base/macros.h" 22 #include "globals.h" 23 24 typedef uint8_t uint4_t; 25 typedef int8_t int4_t; 26 27 namespace art { 28 29 class DexFile; 30 31 enum { 32 kNumPackedOpcodes = 0x100 33 }; 34 35 class Instruction { 36 public: 37 // NOP-encoded switch-statement signatures. 38 enum { 39 kPackedSwitchSignature = 0x0100, 40 kSparseSwitchSignature = 0x0200, 41 kArrayDataSignature = 0x0300, 42 }; 43 44 struct PACKED(4) PackedSwitchPayload { 45 const uint16_t ident; 46 const uint16_t case_count; 47 const int32_t first_key; 48 const int32_t targets[]; 49 50 private: 51 DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload); 52 }; 53 54 struct PACKED(4) SparseSwitchPayload { 55 const uint16_t ident; 56 const uint16_t case_count; 57 const int32_t keys_and_targets[]; 58 59 public: 60 const int32_t* GetKeys() const { 61 return keys_and_targets; 62 } 63 64 const int32_t* GetTargets() const { 65 return keys_and_targets + case_count; 66 } 67 68 private: 69 DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload); 70 }; 71 72 struct PACKED(4) ArrayDataPayload { 73 const uint16_t ident; 74 const uint16_t element_width; 75 const uint32_t element_count; 76 const uint8_t data[]; 77 78 private: 79 DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload); 80 }; 81 82 // TODO: the code layout below is deliberate to avoid this enum being picked up by 83 // generate-operator-out.py. 84 enum Code 85 { // NOLINT(whitespace/braces) 86 #define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode, 87 #include "dex_instruction_list.h" 88 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM) 89 #undef DEX_INSTRUCTION_LIST 90 #undef INSTRUCTION_ENUM 91 }; 92 93 enum Format { 94 k10x, // op 95 k12x, // op vA, vB 96 k11n, // op vA, #+B 97 k11x, // op vAA 98 k10t, // op +AA 99 k20t, // op +AAAA 100 k22x, // op vAA, vBBBB 101 k21t, // op vAA, +BBBB 102 k21s, // op vAA, #+BBBB 103 k21h, // op vAA, #+BBBB00000[00000000] 104 k21c, // op vAA, thing@BBBB 105 k23x, // op vAA, vBB, vCC 106 k22b, // op vAA, vBB, #+CC 107 k22t, // op vA, vB, +CCCC 108 k22s, // op vA, vB, #+CCCC 109 k22c, // op vA, vB, thing@CCCC 110 k32x, // op vAAAA, vBBBB 111 k30t, // op +AAAAAAAA 112 k31t, // op vAA, +BBBBBBBB 113 k31i, // op vAA, #+BBBBBBBB 114 k31c, // op vAA, thing@BBBBBBBB 115 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG) 116 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB 117 k51l, // op vAA, #+BBBBBBBBBBBBBBBB 118 }; 119 120 enum Flags { 121 kBranch = 0x000001, // conditional or unconditional branch 122 kContinue = 0x000002, // flow can continue to next statement 123 kSwitch = 0x000004, // switch statement 124 kThrow = 0x000008, // could cause an exception to be thrown 125 kReturn = 0x000010, // returns, no additional statements 126 kInvoke = 0x000020, // a flavor of invoke 127 kUnconditional = 0x000040, // unconditional branch 128 kAdd = 0x000080, // addition 129 kSubtract = 0x000100, // subtract 130 kMultiply = 0x000200, // multiply 131 kDivide = 0x000400, // division 132 kRemainder = 0x000800, // remainder 133 kAnd = 0x001000, // and 134 kOr = 0x002000, // or 135 kXor = 0x004000, // xor 136 kShl = 0x008000, // shl 137 kShr = 0x010000, // shr 138 kUshr = 0x020000, // ushr 139 kCast = 0x040000, // cast 140 kStore = 0x080000, // store opcode 141 kLoad = 0x100000, // load opcode 142 kClobber = 0x200000, // clobbers memory in a big way (not just a write) 143 kRegCFieldOrConstant = 0x400000, // is the third virtual register a field or literal constant (vC) 144 kRegBFieldOrConstant = 0x800000, // is the second virtual register a field or literal constant (vB) 145 }; 146 147 enum VerifyFlag { 148 kVerifyNone = 0x000000, 149 kVerifyRegA = 0x000001, 150 kVerifyRegAWide = 0x000002, 151 kVerifyRegB = 0x000004, 152 kVerifyRegBField = 0x000008, 153 kVerifyRegBMethod = 0x000010, 154 kVerifyRegBNewInstance = 0x000020, 155 kVerifyRegBString = 0x000040, 156 kVerifyRegBType = 0x000080, 157 kVerifyRegBWide = 0x000100, 158 kVerifyRegC = 0x000200, 159 kVerifyRegCField = 0x000400, 160 kVerifyRegCNewArray = 0x000800, 161 kVerifyRegCType = 0x001000, 162 kVerifyRegCWide = 0x002000, 163 kVerifyArrayData = 0x004000, 164 kVerifyBranchTarget = 0x008000, 165 kVerifySwitchTargets = 0x010000, 166 kVerifyVarArg = 0x020000, 167 kVerifyVarArgNonZero = 0x040000, 168 kVerifyVarArgRange = 0x080000, 169 kVerifyVarArgRangeNonZero = 0x100000, 170 kVerifyRuntimeOnly = 0x200000, 171 kVerifyError = 0x400000, 172 }; 173 174 static constexpr uint32_t kMaxVarArgRegs = 5; 175 176 // Returns the size (in 2 byte code units) of this instruction. 177 size_t SizeInCodeUnits() const { 178 int result = kInstructionSizeInCodeUnits[Opcode()]; 179 if (UNLIKELY(result < 0)) { 180 return SizeInCodeUnitsComplexOpcode(); 181 } else { 182 return static_cast<size_t>(result); 183 } 184 } 185 186 // Reads an instruction out of the stream at the specified address. 187 static const Instruction* At(const uint16_t* code) { 188 DCHECK(code != NULL); 189 return reinterpret_cast<const Instruction*>(code); 190 } 191 192 // Reads an instruction out of the stream from the current address plus an offset. 193 const Instruction* RelativeAt(int32_t offset) const { 194 return At(reinterpret_cast<const uint16_t*>(this) + offset); 195 } 196 197 // Returns a pointer to the next instruction in the stream. 198 const Instruction* Next() const { 199 return RelativeAt(SizeInCodeUnits()); 200 } 201 202 // Returns a pointer to the instruction after this 1xx instruction in the stream. 203 const Instruction* Next_1xx() const { 204 DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t); 205 return RelativeAt(1); 206 } 207 208 // Returns a pointer to the instruction after this 2xx instruction in the stream. 209 const Instruction* Next_2xx() const { 210 DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c); 211 return RelativeAt(2); 212 } 213 214 // Returns a pointer to the instruction after this 3xx instruction in the stream. 215 const Instruction* Next_3xx() const { 216 DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc); 217 return RelativeAt(3); 218 } 219 220 // Returns a pointer to the instruction after this 51l instruction in the stream. 221 const Instruction* Next_51l() const { 222 DCHECK(FormatOf(Opcode()) == k51l); 223 return RelativeAt(5); 224 } 225 226 // Returns the name of this instruction's opcode. 227 const char* Name() const { 228 return Instruction::Name(Opcode()); 229 } 230 231 // Returns the name of the given opcode. 232 static const char* Name(Code opcode) { 233 return kInstructionNames[opcode]; 234 } 235 236 // VRegA 237 bool HasVRegA() const; 238 int32_t VRegA() const; 239 240 int8_t VRegA_10t() const { 241 return VRegA_10t(Fetch16(0)); 242 } 243 uint8_t VRegA_10x() const { 244 return VRegA_10x(Fetch16(0)); 245 } 246 uint4_t VRegA_11n() const { 247 return VRegA_11n(Fetch16(0)); 248 } 249 uint8_t VRegA_11x() const { 250 return VRegA_11x(Fetch16(0)); 251 } 252 uint4_t VRegA_12x() const { 253 return VRegA_12x(Fetch16(0)); 254 } 255 int16_t VRegA_20t() const; 256 uint8_t VRegA_21c() const { 257 return VRegA_21c(Fetch16(0)); 258 } 259 uint8_t VRegA_21h() const { 260 return VRegA_21h(Fetch16(0)); 261 } 262 uint8_t VRegA_21s() const { 263 return VRegA_21s(Fetch16(0)); 264 } 265 uint8_t VRegA_21t() const { 266 return VRegA_21t(Fetch16(0)); 267 } 268 uint8_t VRegA_22b() const { 269 return VRegA_22b(Fetch16(0)); 270 } 271 uint4_t VRegA_22c() const { 272 return VRegA_22c(Fetch16(0)); 273 } 274 uint4_t VRegA_22s() const { 275 return VRegA_22s(Fetch16(0)); 276 } 277 uint4_t VRegA_22t() const { 278 return VRegA_22t(Fetch16(0)); 279 } 280 uint8_t VRegA_22x() const { 281 return VRegA_22x(Fetch16(0)); 282 } 283 uint8_t VRegA_23x() const { 284 return VRegA_23x(Fetch16(0)); 285 } 286 int32_t VRegA_30t() const; 287 uint8_t VRegA_31c() const { 288 return VRegA_31c(Fetch16(0)); 289 } 290 uint8_t VRegA_31i() const { 291 return VRegA_31i(Fetch16(0)); 292 } 293 uint8_t VRegA_31t() const { 294 return VRegA_31t(Fetch16(0)); 295 } 296 uint16_t VRegA_32x() const; 297 uint4_t VRegA_35c() const { 298 return VRegA_35c(Fetch16(0)); 299 } 300 uint8_t VRegA_3rc() const { 301 return VRegA_3rc(Fetch16(0)); 302 } 303 uint8_t VRegA_51l() const { 304 return VRegA_51l(Fetch16(0)); 305 } 306 307 // The following methods return the vA operand for various instruction formats. The "inst_data" 308 // parameter holds the first 16 bits of instruction which the returned value is decoded from. 309 int8_t VRegA_10t(uint16_t inst_data) const; 310 uint8_t VRegA_10x(uint16_t inst_data) const; 311 uint4_t VRegA_11n(uint16_t inst_data) const; 312 uint8_t VRegA_11x(uint16_t inst_data) const; 313 uint4_t VRegA_12x(uint16_t inst_data) const; 314 uint8_t VRegA_21c(uint16_t inst_data) const; 315 uint8_t VRegA_21h(uint16_t inst_data) const; 316 uint8_t VRegA_21s(uint16_t inst_data) const; 317 uint8_t VRegA_21t(uint16_t inst_data) const; 318 uint8_t VRegA_22b(uint16_t inst_data) const; 319 uint4_t VRegA_22c(uint16_t inst_data) const; 320 uint4_t VRegA_22s(uint16_t inst_data) const; 321 uint4_t VRegA_22t(uint16_t inst_data) const; 322 uint8_t VRegA_22x(uint16_t inst_data) const; 323 uint8_t VRegA_23x(uint16_t inst_data) const; 324 uint8_t VRegA_31c(uint16_t inst_data) const; 325 uint8_t VRegA_31i(uint16_t inst_data) const; 326 uint8_t VRegA_31t(uint16_t inst_data) const; 327 uint4_t VRegA_35c(uint16_t inst_data) const; 328 uint8_t VRegA_3rc(uint16_t inst_data) const; 329 uint8_t VRegA_51l(uint16_t inst_data) const; 330 331 // VRegB 332 bool HasVRegB() const; 333 int32_t VRegB() const; 334 335 bool HasWideVRegB() const; 336 uint64_t WideVRegB() const; 337 338 int4_t VRegB_11n() const { 339 return VRegB_11n(Fetch16(0)); 340 } 341 uint4_t VRegB_12x() const { 342 return VRegB_12x(Fetch16(0)); 343 } 344 uint16_t VRegB_21c() const; 345 uint16_t VRegB_21h() const; 346 int16_t VRegB_21s() const; 347 int16_t VRegB_21t() const; 348 uint8_t VRegB_22b() const; 349 uint4_t VRegB_22c() const { 350 return VRegB_22c(Fetch16(0)); 351 } 352 uint4_t VRegB_22s() const { 353 return VRegB_22s(Fetch16(0)); 354 } 355 uint4_t VRegB_22t() const { 356 return VRegB_22t(Fetch16(0)); 357 } 358 uint16_t VRegB_22x() const; 359 uint8_t VRegB_23x() const; 360 uint32_t VRegB_31c() const; 361 int32_t VRegB_31i() const; 362 int32_t VRegB_31t() const; 363 uint16_t VRegB_32x() const; 364 uint16_t VRegB_35c() const; 365 uint16_t VRegB_3rc() const; 366 uint64_t VRegB_51l() const; // vB_wide 367 368 // The following methods return the vB operand for all instruction formats where it is encoded in 369 // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned 370 // value is decoded from it. 371 int4_t VRegB_11n(uint16_t inst_data) const; 372 uint4_t VRegB_12x(uint16_t inst_data) const; 373 uint4_t VRegB_22c(uint16_t inst_data) const; 374 uint4_t VRegB_22s(uint16_t inst_data) const; 375 uint4_t VRegB_22t(uint16_t inst_data) const; 376 377 // VRegC 378 bool HasVRegC() const; 379 int32_t VRegC() const; 380 381 int8_t VRegC_22b() const; 382 uint16_t VRegC_22c() const; 383 int16_t VRegC_22s() const; 384 int16_t VRegC_22t() const; 385 uint8_t VRegC_23x() const; 386 uint4_t VRegC_35c() const; 387 uint16_t VRegC_3rc() const; 388 389 // Fills the given array with the 'arg' array of the instruction. 390 bool HasVarArgs() const; 391 void GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const; 392 void GetVarArgs(uint32_t args[kMaxVarArgRegs]) const { 393 return GetVarArgs(args, Fetch16(0)); 394 } 395 396 // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first 397 // 16 bits of instruction. 398 Code Opcode(uint16_t inst_data) const { 399 DCHECK_EQ(inst_data, Fetch16(0)); 400 return static_cast<Code>(inst_data & 0xFF); 401 } 402 403 // Returns the opcode field of the instruction from the first 16 bits of instruction. 404 Code Opcode() const { 405 return Opcode(Fetch16(0)); 406 } 407 408 void SetOpcode(Code opcode) { 409 DCHECK_LT(static_cast<uint16_t>(opcode), 256u); 410 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 411 insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode); 412 } 413 414 void SetVRegA_10x(uint8_t val) { 415 DCHECK(FormatOf(Opcode()) == k10x); 416 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 417 insns[0] = (val << 8) | (insns[0] & 0x00ff); 418 } 419 420 void SetVRegB_3rc(uint16_t val) { 421 DCHECK(FormatOf(Opcode()) == k3rc); 422 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 423 insns[1] = val; 424 } 425 426 void SetVRegB_35c(uint16_t val) { 427 DCHECK(FormatOf(Opcode()) == k35c); 428 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 429 insns[1] = val; 430 } 431 432 void SetVRegC_22c(uint16_t val) { 433 DCHECK(FormatOf(Opcode()) == k22c); 434 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 435 insns[1] = val; 436 } 437 438 // Returns the format of the given opcode. 439 static Format FormatOf(Code opcode) { 440 return kInstructionFormats[opcode]; 441 } 442 443 // Returns the flags for the given opcode. 444 static int FlagsOf(Code opcode) { 445 return kInstructionFlags[opcode]; 446 } 447 448 // Return the verify flags for the given opcode. 449 static int VerifyFlagsOf(Code opcode) { 450 return kInstructionVerifyFlags[opcode]; 451 } 452 453 // Returns true if this instruction is a branch. 454 bool IsBranch() const { 455 return (kInstructionFlags[Opcode()] & kBranch) != 0; 456 } 457 458 // Returns true if this instruction is a unconditional branch. 459 bool IsUnconditional() const { 460 return (kInstructionFlags[Opcode()] & kUnconditional) != 0; 461 } 462 463 // Returns the branch offset if this instruction is a branch. 464 int32_t GetTargetOffset() const; 465 466 // Returns true if the instruction allows control flow to go to the following instruction. 467 bool CanFlowThrough() const; 468 469 // Returns true if this instruction is a switch. 470 bool IsSwitch() const { 471 return (kInstructionFlags[Opcode()] & kSwitch) != 0; 472 } 473 474 // Returns true if this instruction can throw. 475 bool IsThrow() const { 476 return (kInstructionFlags[Opcode()] & kThrow) != 0; 477 } 478 479 // Determine if the instruction is any of 'return' instructions. 480 bool IsReturn() const { 481 return (kInstructionFlags[Opcode()] & kReturn) != 0; 482 } 483 484 // Determine if this instruction ends execution of its basic block. 485 bool IsBasicBlockEnd() const { 486 return IsBranch() || IsReturn() || Opcode() == THROW; 487 } 488 489 // Determine if this instruction is an invoke. 490 bool IsInvoke() const { 491 return (kInstructionFlags[Opcode()] & kInvoke) != 0; 492 } 493 494 int GetVerifyTypeArgumentA() const { 495 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide)); 496 } 497 498 int GetVerifyTypeArgumentB() const { 499 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | 500 kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | 501 kVerifyRegBWide)); 502 } 503 504 int GetVerifyTypeArgumentC() const { 505 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField | 506 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide)); 507 } 508 509 int GetVerifyExtraFlags() const { 510 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget | 511 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | kVerifyVarArgRange | 512 kVerifyVarArgRangeNonZero | kVerifyError)); 513 } 514 515 bool GetVerifyIsRuntimeOnly() const { 516 return (kInstructionVerifyFlags[Opcode()] & kVerifyRuntimeOnly) != 0; 517 } 518 519 // Get the dex PC of this instruction as a offset in code units from the beginning of insns. 520 uint32_t GetDexPc(const uint16_t* insns) const { 521 return (reinterpret_cast<const uint16_t*>(this) - insns); 522 } 523 524 // Dump decoded version of instruction 525 std::string DumpString(const DexFile*) const; 526 527 // Dump code_units worth of this instruction, padding to code_units for shorter instructions 528 std::string DumpHex(size_t code_units) const; 529 530 uint16_t Fetch16(size_t offset) const { 531 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this); 532 return insns[offset]; 533 } 534 535 private: 536 size_t SizeInCodeUnitsComplexOpcode() const; 537 538 uint32_t Fetch32(size_t offset) const { 539 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16)); 540 } 541 542 uint4_t InstA() const { 543 return InstA(Fetch16(0)); 544 } 545 546 uint4_t InstB() const { 547 return InstB(Fetch16(0)); 548 } 549 550 uint8_t InstAA() const { 551 return InstAA(Fetch16(0)); 552 } 553 554 uint4_t InstA(uint16_t inst_data) const { 555 DCHECK_EQ(inst_data, Fetch16(0)); 556 return static_cast<uint4_t>((inst_data >> 8) & 0x0f); 557 } 558 559 uint4_t InstB(uint16_t inst_data) const { 560 DCHECK_EQ(inst_data, Fetch16(0)); 561 return static_cast<uint4_t>(inst_data >> 12); 562 } 563 564 uint8_t InstAA(uint16_t inst_data) const { 565 DCHECK_EQ(inst_data, Fetch16(0)); 566 return static_cast<uint8_t>(inst_data >> 8); 567 } 568 569 static const char* const kInstructionNames[]; 570 static Format const kInstructionFormats[]; 571 static int const kInstructionFlags[]; 572 static int const kInstructionVerifyFlags[]; 573 static int const kInstructionSizeInCodeUnits[]; 574 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); 575 }; 576 std::ostream& operator<<(std::ostream& os, const Instruction::Code& code); 577 std::ostream& operator<<(std::ostream& os, const Instruction::Format& format); 578 std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags); 579 std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags); 580 581 } // namespace art 582 583 #endif // ART_RUNTIME_DEX_INSTRUCTION_H_ 584