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 = 0x01, // conditional or unconditional branch 122 kContinue = 0x02, // flow can continue to next statement 123 kSwitch = 0x04, // switch statement 124 kThrow = 0x08, // could cause an exception to be thrown 125 kReturn = 0x10, // returns, no additional statements 126 kInvoke = 0x20, // a flavor of invoke 127 kUnconditional = 0x40, // unconditional branch 128 }; 129 130 enum VerifyFlag { 131 kVerifyNone = 0x00000, 132 kVerifyRegA = 0x00001, 133 kVerifyRegAWide = 0x00002, 134 kVerifyRegB = 0x00004, 135 kVerifyRegBField = 0x00008, 136 kVerifyRegBMethod = 0x00010, 137 kVerifyRegBNewInstance = 0x00020, 138 kVerifyRegBString = 0x00040, 139 kVerifyRegBType = 0x00080, 140 kVerifyRegBWide = 0x00100, 141 kVerifyRegC = 0x00200, 142 kVerifyRegCField = 0x00400, 143 kVerifyRegCNewArray = 0x00800, 144 kVerifyRegCType = 0x01000, 145 kVerifyRegCWide = 0x02000, 146 kVerifyArrayData = 0x04000, 147 kVerifyBranchTarget = 0x08000, 148 kVerifySwitchTargets = 0x10000, 149 kVerifyVarArg = 0x20000, 150 kVerifyVarArgRange = 0x40000, 151 kVerifyError = 0x80000, 152 }; 153 154 // Decodes this instruction, populating its arguments. 155 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const; 156 157 // Returns the size (in 2 byte code units) of this instruction. 158 size_t SizeInCodeUnits() const { 159 int result = kInstructionSizeInCodeUnits[Opcode()]; 160 if (UNLIKELY(result < 0)) { 161 return SizeInCodeUnitsComplexOpcode(); 162 } else { 163 return static_cast<size_t>(result); 164 } 165 } 166 167 // Reads an instruction out of the stream at the specified address. 168 static const Instruction* At(const uint16_t* code) { 169 DCHECK(code != NULL); 170 return reinterpret_cast<const Instruction*>(code); 171 } 172 173 // Reads an instruction out of the stream from the current address plus an offset. 174 const Instruction* RelativeAt(int32_t offset) const { 175 return At(reinterpret_cast<const uint16_t*>(this) + offset); 176 } 177 178 // Returns a pointer to the next instruction in the stream. 179 const Instruction* Next() const { 180 return RelativeAt(SizeInCodeUnits()); 181 } 182 183 // Returns a pointer to the instruction after this 1xx instruction in the stream. 184 const Instruction* Next_1xx() const { 185 DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t); 186 return RelativeAt(1); 187 } 188 189 // Returns a pointer to the instruction after this 2xx instruction in the stream. 190 const Instruction* Next_2xx() const { 191 DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c); 192 return RelativeAt(2); 193 } 194 195 // Returns a pointer to the instruction after this 3xx instruction in the stream. 196 const Instruction* Next_3xx() const { 197 DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc); 198 return RelativeAt(3); 199 } 200 201 // Returns a pointer to the instruction after this 51l instruction in the stream. 202 const Instruction* Next_51l() const { 203 DCHECK(FormatOf(Opcode()) == k51l); 204 return RelativeAt(5); 205 } 206 207 // Returns the name of this instruction's opcode. 208 const char* Name() const { 209 return Instruction::Name(Opcode()); 210 } 211 212 // Returns the name of the given opcode. 213 static const char* Name(Code opcode) { 214 return kInstructionNames[opcode]; 215 } 216 217 // VRegA 218 bool HasVRegA() const; 219 int32_t VRegA() const; 220 int8_t VRegA_10t() const; 221 uint8_t VRegA_10x() const; 222 uint4_t VRegA_11n() const; 223 uint8_t VRegA_11x() const; 224 uint4_t VRegA_12x() const; 225 int16_t VRegA_20t() const; 226 uint8_t VRegA_21c() const; 227 uint8_t VRegA_21h() const; 228 uint8_t VRegA_21s() const; 229 uint8_t VRegA_21t() const; 230 uint8_t VRegA_22b() const; 231 uint4_t VRegA_22c() const; 232 uint4_t VRegA_22s() const; 233 uint4_t VRegA_22t() const; 234 uint8_t VRegA_22x() const; 235 uint8_t VRegA_23x() const; 236 int32_t VRegA_30t() const; 237 uint8_t VRegA_31c() const; 238 uint8_t VRegA_31i() const; 239 uint8_t VRegA_31t() const; 240 uint16_t VRegA_32x() const; 241 uint4_t VRegA_35c() const; 242 uint8_t VRegA_3rc() const; 243 uint8_t VRegA_51l() const; 244 245 // VRegB 246 bool HasVRegB() const; 247 int32_t VRegB() const; 248 int4_t VRegB_11n() const; 249 uint4_t VRegB_12x() const; 250 uint16_t VRegB_21c() const; 251 uint16_t VRegB_21h() const; 252 int16_t VRegB_21s() const; 253 int16_t VRegB_21t() const; 254 uint8_t VRegB_22b() const; 255 uint4_t VRegB_22c() const; 256 uint4_t VRegB_22s() const; 257 uint4_t VRegB_22t() const; 258 uint16_t VRegB_22x() const; 259 uint8_t VRegB_23x() const; 260 uint32_t VRegB_31c() const; 261 int32_t VRegB_31i() const; 262 int32_t VRegB_31t() const; 263 uint16_t VRegB_32x() const; 264 uint16_t VRegB_35c() const; 265 uint16_t VRegB_3rc() const; 266 uint64_t VRegB_51l() const; // vB_wide 267 268 // VRegC 269 bool HasVRegC() const; 270 int32_t VRegC() const; 271 int8_t VRegC_22b() const; 272 uint16_t VRegC_22c() const; 273 int16_t VRegC_22s() const; 274 int16_t VRegC_22t() const; 275 uint8_t VRegC_23x() const; 276 uint4_t VRegC_35c() const; 277 uint16_t VRegC_3rc() const; 278 279 // Fills the given array with the 'arg' array of the instruction. 280 void GetArgs(uint32_t args[5]) const; 281 282 // Returns the opcode field of the instruction. 283 Code Opcode() const { 284 return static_cast<Code>(Fetch16(0) & 0xFF); 285 } 286 287 void SetOpcode(Code opcode) { 288 DCHECK_LT(static_cast<uint16_t>(opcode), 256u); 289 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 290 insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode); 291 } 292 293 void SetVRegA_10x(uint8_t val) { 294 DCHECK(FormatOf(Opcode()) == k10x); 295 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 296 insns[0] = (val << 8) | (insns[0] & 0x00ff); 297 } 298 299 void SetVRegB_3rc(uint16_t val) { 300 DCHECK(FormatOf(Opcode()) == k3rc); 301 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 302 insns[1] = val; 303 } 304 305 void SetVRegB_35c(uint16_t val) { 306 DCHECK(FormatOf(Opcode()) == k35c); 307 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 308 insns[1] = val; 309 } 310 311 void SetVRegC_22c(uint16_t val) { 312 DCHECK(FormatOf(Opcode()) == k22c); 313 uint16_t* insns = reinterpret_cast<uint16_t*>(this); 314 insns[1] = val; 315 } 316 317 // Returns the format of the given opcode. 318 static Format FormatOf(Code opcode) { 319 return kInstructionFormats[opcode]; 320 } 321 322 // Returns the flags for the given opcode. 323 static int FlagsOf(Code opcode) { 324 return kInstructionFlags[opcode]; 325 } 326 327 // Returns true if this instruction is a branch. 328 bool IsBranch() const { 329 return (kInstructionFlags[Opcode()] & kBranch) != 0; 330 } 331 332 // Returns true if this instruction is a unconditional branch. 333 bool IsUnconditional() const { 334 return (kInstructionFlags[Opcode()] & kUnconditional) != 0; 335 } 336 337 // Returns the branch offset if this instruction is a branch. 338 int32_t GetTargetOffset() const; 339 340 // Returns true if the instruction allows control flow to go to the following instruction. 341 bool CanFlowThrough() const; 342 343 // Returns true if this instruction is a switch. 344 bool IsSwitch() const { 345 return (kInstructionFlags[Opcode()] & kSwitch) != 0; 346 } 347 348 // Returns true if this instruction can throw. 349 bool IsThrow() const { 350 return (kInstructionFlags[Opcode()] & kThrow) != 0; 351 } 352 353 // Determine if the instruction is any of 'return' instructions. 354 bool IsReturn() const { 355 return (kInstructionFlags[Opcode()] & kReturn) != 0; 356 } 357 358 // Determine if this instruction ends execution of its basic block. 359 bool IsBasicBlockEnd() const { 360 return IsBranch() || IsReturn() || Opcode() == THROW; 361 } 362 363 // Determine if this instruction is an invoke. 364 bool IsInvoke() const { 365 return (kInstructionFlags[Opcode()] & kInvoke) != 0; 366 } 367 368 int GetVerifyTypeArgumentA() const { 369 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide)); 370 } 371 372 int GetVerifyTypeArgumentB() const { 373 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod | 374 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide)); 375 } 376 377 int GetVerifyTypeArgumentC() const { 378 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField | 379 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide)); 380 } 381 382 int GetVerifyExtraFlags() const { 383 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget | 384 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError)); 385 } 386 387 // Get the dex PC of this instruction as a offset in code units from the beginning of insns. 388 uint32_t GetDexPc(const uint16_t* insns) const { 389 return (reinterpret_cast<const uint16_t*>(this) - insns); 390 } 391 392 // Dump decoded version of instruction 393 std::string DumpString(const DexFile*) const; 394 395 // Dump code_units worth of this instruction, padding to code_units for shorter instructions 396 std::string DumpHex(size_t code_units) const; 397 398 private: 399 size_t SizeInCodeUnitsComplexOpcode() const; 400 401 uint16_t Fetch16(size_t offset) const { 402 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this); 403 return insns[offset]; 404 } 405 406 uint32_t Fetch32(size_t offset) const { 407 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16)); 408 } 409 410 uint4_t InstA() const { 411 return static_cast<uint4_t>((Fetch16(0) >> 8) & 0x0f); 412 } 413 414 uint4_t InstB() const { 415 return static_cast<uint4_t>(Fetch16(0) >> 12); 416 } 417 418 uint8_t InstAA() const { 419 return static_cast<uint8_t>(Fetch16(0) >> 8); 420 } 421 422 static const char* const kInstructionNames[]; 423 static Format const kInstructionFormats[]; 424 static int const kInstructionFlags[]; 425 static int const kInstructionVerifyFlags[]; 426 static int const kInstructionSizeInCodeUnits[]; 427 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); 428 }; 429 std::ostream& operator<<(std::ostream& os, const Instruction::Code& code); 430 std::ostream& operator<<(std::ostream& os, const Instruction::Format& format); 431 std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags); 432 std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags); 433 434 /* 435 * Holds the contents of a decoded instruction. 436 */ 437 struct DecodedInstruction { 438 uint32_t vA; 439 uint32_t vB; 440 uint64_t vB_wide; /* for k51l */ 441 uint32_t vC; 442 uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ 443 Instruction::Code opcode; 444 445 explicit DecodedInstruction(const Instruction* inst) { 446 inst->Decode(vA, vB, vB_wide, vC, arg); 447 opcode = inst->Opcode(); 448 } 449 }; 450 451 } // namespace art 452 453 #endif // ART_RUNTIME_DEX_INSTRUCTION_H_ 454