1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker #ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_ 18*795d594fSAndroid Build Coastguard Worker #define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_ 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h> 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker #include "base/globals.h" 23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 24*795d594fSAndroid Build Coastguard Worker #include "dex_instruction_list.h" 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker using uint4_t = uint8_t; 27*795d594fSAndroid Build Coastguard Worker using int4_t = int8_t; 28*795d594fSAndroid Build Coastguard Worker 29*795d594fSAndroid Build Coastguard Worker namespace art { 30*795d594fSAndroid Build Coastguard Worker 31*795d594fSAndroid Build Coastguard Worker class DexFile; 32*795d594fSAndroid Build Coastguard Worker 33*795d594fSAndroid Build Coastguard Worker // The number of Dalvik opcodes. 34*795d594fSAndroid Build Coastguard Worker static constexpr size_t kNumPackedOpcodes = 0x100; 35*795d594fSAndroid Build Coastguard Worker 36*795d594fSAndroid Build Coastguard Worker class Instruction { 37*795d594fSAndroid Build Coastguard Worker public: 38*795d594fSAndroid Build Coastguard Worker // NOP-encoded switch-statement signatures. 39*795d594fSAndroid Build Coastguard Worker enum Signatures { 40*795d594fSAndroid Build Coastguard Worker kPackedSwitchSignature = 0x0100, 41*795d594fSAndroid Build Coastguard Worker kSparseSwitchSignature = 0x0200, 42*795d594fSAndroid Build Coastguard Worker kArrayDataSignature = 0x0300, 43*795d594fSAndroid Build Coastguard Worker }; 44*795d594fSAndroid Build Coastguard Worker 45*795d594fSAndroid Build Coastguard Worker struct PACKED(4) PackedSwitchPayload { 46*795d594fSAndroid Build Coastguard Worker const uint16_t ident; 47*795d594fSAndroid Build Coastguard Worker const uint16_t case_count; 48*795d594fSAndroid Build Coastguard Worker const int32_t first_key; 49*795d594fSAndroid Build Coastguard Worker const int32_t targets[]; 50*795d594fSAndroid Build Coastguard Worker 51*795d594fSAndroid Build Coastguard Worker private: 52*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload); 53*795d594fSAndroid Build Coastguard Worker }; 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker struct PACKED(4) SparseSwitchPayload { 56*795d594fSAndroid Build Coastguard Worker const uint16_t ident; 57*795d594fSAndroid Build Coastguard Worker const uint16_t case_count; 58*795d594fSAndroid Build Coastguard Worker const int32_t keys_and_targets[]; 59*795d594fSAndroid Build Coastguard Worker 60*795d594fSAndroid Build Coastguard Worker public: GetKeysSparseSwitchPayload61*795d594fSAndroid Build Coastguard Worker const int32_t* GetKeys() const { 62*795d594fSAndroid Build Coastguard Worker return keys_and_targets; 63*795d594fSAndroid Build Coastguard Worker } 64*795d594fSAndroid Build Coastguard Worker GetTargetsSparseSwitchPayload65*795d594fSAndroid Build Coastguard Worker const int32_t* GetTargets() const { 66*795d594fSAndroid Build Coastguard Worker return keys_and_targets + case_count; 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker private: 70*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload); 71*795d594fSAndroid Build Coastguard Worker }; 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker struct PACKED(4) ArrayDataPayload { 74*795d594fSAndroid Build Coastguard Worker const uint16_t ident; 75*795d594fSAndroid Build Coastguard Worker const uint16_t element_width; 76*795d594fSAndroid Build Coastguard Worker const uint32_t element_count; 77*795d594fSAndroid Build Coastguard Worker const uint8_t data[]; 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker private: 80*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload); 81*795d594fSAndroid Build Coastguard Worker }; 82*795d594fSAndroid Build Coastguard Worker 83*795d594fSAndroid Build Coastguard Worker enum Code { // private marker to avoid generate-operator-out.py from processing. 84*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_ENUM(opcode, cname, p, f, i, a, e, v) cname = (opcode), 85*795d594fSAndroid Build Coastguard Worker DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM) 86*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_ENUM 87*795d594fSAndroid Build Coastguard Worker RSUB_INT_LIT16 = RSUB_INT, 88*795d594fSAndroid Build Coastguard Worker }; 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker enum Format : uint8_t { 91*795d594fSAndroid Build Coastguard Worker k10x, // op 92*795d594fSAndroid Build Coastguard Worker k12x, // op vA, vB 93*795d594fSAndroid Build Coastguard Worker k11n, // op vA, #+B 94*795d594fSAndroid Build Coastguard Worker k11x, // op vAA 95*795d594fSAndroid Build Coastguard Worker k10t, // op +AA 96*795d594fSAndroid Build Coastguard Worker k20t, // op +AAAA 97*795d594fSAndroid Build Coastguard Worker k22x, // op vAA, vBBBB 98*795d594fSAndroid Build Coastguard Worker k21t, // op vAA, +BBBB 99*795d594fSAndroid Build Coastguard Worker k21s, // op vAA, #+BBBB 100*795d594fSAndroid Build Coastguard Worker k21h, // op vAA, #+BBBB00000[00000000] 101*795d594fSAndroid Build Coastguard Worker k21c, // op vAA, thing@BBBB 102*795d594fSAndroid Build Coastguard Worker k23x, // op vAA, vBB, vCC 103*795d594fSAndroid Build Coastguard Worker k22b, // op vAA, vBB, #+CC 104*795d594fSAndroid Build Coastguard Worker k22t, // op vA, vB, +CCCC 105*795d594fSAndroid Build Coastguard Worker k22s, // op vA, vB, #+CCCC 106*795d594fSAndroid Build Coastguard Worker k22c, // op vA, vB, thing@CCCC 107*795d594fSAndroid Build Coastguard Worker k32x, // op vAAAA, vBBBB 108*795d594fSAndroid Build Coastguard Worker k30t, // op +AAAAAAAA 109*795d594fSAndroid Build Coastguard Worker k31t, // op vAA, +BBBBBBBB 110*795d594fSAndroid Build Coastguard Worker k31i, // op vAA, #+BBBBBBBB 111*795d594fSAndroid Build Coastguard Worker k31c, // op vAA, thing@BBBBBBBB 112*795d594fSAndroid Build Coastguard Worker k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG) 113*795d594fSAndroid Build Coastguard Worker k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker // op {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH (A: count) 116*795d594fSAndroid Build Coastguard Worker // format: AG op BBBB FEDC HHHH 117*795d594fSAndroid Build Coastguard Worker k45cc, 118*795d594fSAndroid Build Coastguard Worker 119*795d594fSAndroid Build Coastguard Worker // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH (AA: count) 120*795d594fSAndroid Build Coastguard Worker // format: AA op BBBB CCCC HHHH 121*795d594fSAndroid Build Coastguard Worker k4rcc, // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH (AA: count) 122*795d594fSAndroid Build Coastguard Worker 123*795d594fSAndroid Build Coastguard Worker k51l, // op vAA, #+BBBBBBBBBBBBBBBB 124*795d594fSAndroid Build Coastguard Worker kInvalidFormat, 125*795d594fSAndroid Build Coastguard Worker }; 126*795d594fSAndroid Build Coastguard Worker 127*795d594fSAndroid Build Coastguard Worker enum IndexType : uint8_t { 128*795d594fSAndroid Build Coastguard Worker kIndexUnknown = 0, 129*795d594fSAndroid Build Coastguard Worker kIndexNone, // has no index 130*795d594fSAndroid Build Coastguard Worker kIndexTypeRef, // type reference index 131*795d594fSAndroid Build Coastguard Worker kIndexStringRef, // string reference index 132*795d594fSAndroid Build Coastguard Worker kIndexMethodRef, // method reference index 133*795d594fSAndroid Build Coastguard Worker kIndexFieldRef, // field reference index 134*795d594fSAndroid Build Coastguard Worker kIndexMethodAndProtoRef, // method and a proto reference index (for invoke-polymorphic) 135*795d594fSAndroid Build Coastguard Worker kIndexCallSiteRef, // call site reference index 136*795d594fSAndroid Build Coastguard Worker kIndexMethodHandleRef, // constant method handle reference index 137*795d594fSAndroid Build Coastguard Worker kIndexProtoRef, // prototype reference index 138*795d594fSAndroid Build Coastguard Worker }; 139*795d594fSAndroid Build Coastguard Worker 140*795d594fSAndroid Build Coastguard Worker enum Flags : uint8_t { // private marker to avoid generate-operator-out.py from processing. 141*795d594fSAndroid Build Coastguard Worker kBranch = 0x01, // conditional or unconditional branch 142*795d594fSAndroid Build Coastguard Worker kContinue = 0x02, // flow can continue to next statement 143*795d594fSAndroid Build Coastguard Worker kSwitch = 0x04, // switch statement 144*795d594fSAndroid Build Coastguard Worker kThrow = 0x08, // could cause an exception to be thrown 145*795d594fSAndroid Build Coastguard Worker kReturn = 0x10, // returns, no additional statements 146*795d594fSAndroid Build Coastguard Worker kInvoke = 0x20, // a flavor of invoke 147*795d594fSAndroid Build Coastguard Worker kUnconditional = 0x40, // unconditional branch 148*795d594fSAndroid Build Coastguard Worker kExperimental = 0x80, // is an experimental opcode 149*795d594fSAndroid Build Coastguard Worker }; 150*795d594fSAndroid Build Coastguard Worker 151*795d594fSAndroid Build Coastguard Worker // Old flags. Keeping them around in case we might need them again some day. 152*795d594fSAndroid Build Coastguard Worker enum ExtendedFlags : uint32_t { 153*795d594fSAndroid Build Coastguard Worker kAdd = 0x0000080, // addition 154*795d594fSAndroid Build Coastguard Worker kSubtract = 0x0000100, // subtract 155*795d594fSAndroid Build Coastguard Worker kMultiply = 0x0000200, // multiply 156*795d594fSAndroid Build Coastguard Worker kDivide = 0x0000400, // division 157*795d594fSAndroid Build Coastguard Worker kRemainder = 0x0000800, // remainder 158*795d594fSAndroid Build Coastguard Worker kAnd = 0x0001000, // and 159*795d594fSAndroid Build Coastguard Worker kOr = 0x0002000, // or 160*795d594fSAndroid Build Coastguard Worker kXor = 0x0004000, // xor 161*795d594fSAndroid Build Coastguard Worker kShl = 0x0008000, // shl 162*795d594fSAndroid Build Coastguard Worker kShr = 0x0010000, // shr 163*795d594fSAndroid Build Coastguard Worker kUshr = 0x0020000, // ushr 164*795d594fSAndroid Build Coastguard Worker kCast = 0x0040000, // cast 165*795d594fSAndroid Build Coastguard Worker kStore = 0x0080000, // store opcode 166*795d594fSAndroid Build Coastguard Worker kLoad = 0x0100000, // load opcode 167*795d594fSAndroid Build Coastguard Worker kClobber = 0x0200000, // clobbers memory in a big way (not just a write) 168*795d594fSAndroid Build Coastguard Worker kRegCFieldOrConstant = 0x0400000, // is the third virtual register a field or literal constant (vC) 169*795d594fSAndroid Build Coastguard Worker kRegBFieldOrConstant = 0x0800000, // is the second virtual register a field or literal constant (vB) 170*795d594fSAndroid Build Coastguard Worker }; 171*795d594fSAndroid Build Coastguard Worker 172*795d594fSAndroid Build Coastguard Worker enum VerifyFlag : uint32_t { // private marker to avoid generate-operator-out.py from processing. 173*795d594fSAndroid Build Coastguard Worker kVerifyNothing = 0x0000000, 174*795d594fSAndroid Build Coastguard Worker kVerifyRegA = 0x0000001, 175*795d594fSAndroid Build Coastguard Worker kVerifyRegAWide = 0x0000002, 176*795d594fSAndroid Build Coastguard Worker kVerifyRegB = 0x0000004, 177*795d594fSAndroid Build Coastguard Worker kVerifyRegBField = 0x0000008, 178*795d594fSAndroid Build Coastguard Worker kVerifyRegBMethod = 0x0000010, 179*795d594fSAndroid Build Coastguard Worker kVerifyRegBNewInstance = 0x0000020, 180*795d594fSAndroid Build Coastguard Worker kVerifyRegBString = 0x0000040, 181*795d594fSAndroid Build Coastguard Worker kVerifyRegBType = 0x0000080, 182*795d594fSAndroid Build Coastguard Worker kVerifyRegBWide = 0x0000100, 183*795d594fSAndroid Build Coastguard Worker kVerifyRegC = 0x0000200, 184*795d594fSAndroid Build Coastguard Worker kVerifyRegCField = 0x0000400, 185*795d594fSAndroid Build Coastguard Worker kVerifyRegCNewArray = 0x0000800, 186*795d594fSAndroid Build Coastguard Worker kVerifyRegCType = 0x0001000, 187*795d594fSAndroid Build Coastguard Worker kVerifyRegCWide = 0x0002000, 188*795d594fSAndroid Build Coastguard Worker kVerifyArrayData = 0x0004000, 189*795d594fSAndroid Build Coastguard Worker kVerifyBranchTarget = 0x0008000, 190*795d594fSAndroid Build Coastguard Worker kVerifySwitchTargets = 0x0010000, 191*795d594fSAndroid Build Coastguard Worker kVerifyVarArg = 0x0020000, 192*795d594fSAndroid Build Coastguard Worker kVerifyVarArgNonZero = 0x0040000, 193*795d594fSAndroid Build Coastguard Worker kVerifyVarArgRange = 0x0080000, 194*795d594fSAndroid Build Coastguard Worker kVerifyVarArgRangeNonZero = 0x0100000, 195*795d594fSAndroid Build Coastguard Worker kVerifyError = 0x0200000, 196*795d594fSAndroid Build Coastguard Worker kVerifyRegHPrototype = 0x0400000, 197*795d594fSAndroid Build Coastguard Worker kVerifyRegBCallSite = 0x0800000, 198*795d594fSAndroid Build Coastguard Worker kVerifyRegBMethodHandle = 0x1000000, 199*795d594fSAndroid Build Coastguard Worker kVerifyRegBPrototype = 0x2000000, 200*795d594fSAndroid Build Coastguard Worker }; 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker // Collect the enums in a struct for better locality. 203*795d594fSAndroid Build Coastguard Worker struct InstructionDescriptor { 204*795d594fSAndroid Build Coastguard Worker uint32_t verify_flags; // Set of VerifyFlag. 205*795d594fSAndroid Build Coastguard Worker Format format; 206*795d594fSAndroid Build Coastguard Worker IndexType index_type; 207*795d594fSAndroid Build Coastguard Worker uint8_t flags; // Set of Flags. 208*795d594fSAndroid Build Coastguard Worker int8_t size_in_code_units; 209*795d594fSAndroid Build Coastguard Worker }; 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kMaxVarArgRegs = 5; 212*795d594fSAndroid Build Coastguard Worker 213*795d594fSAndroid Build Coastguard Worker static constexpr bool kHaveExperimentalInstructions = false; 214*795d594fSAndroid Build Coastguard Worker 215*795d594fSAndroid Build Coastguard Worker // Returns the size (in 2 byte code units) of this instruction. SizeInCodeUnits()216*795d594fSAndroid Build Coastguard Worker size_t SizeInCodeUnits() const { 217*795d594fSAndroid Build Coastguard Worker int8_t result = InstructionDescriptorOf(Opcode()).size_in_code_units; 218*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(result < 0)) { 219*795d594fSAndroid Build Coastguard Worker return SizeInCodeUnitsComplexOpcode(); 220*795d594fSAndroid Build Coastguard Worker } else { 221*795d594fSAndroid Build Coastguard Worker return static_cast<size_t>(result); 222*795d594fSAndroid Build Coastguard Worker } 223*795d594fSAndroid Build Coastguard Worker } 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker // Returns the size (in 2 byte code units) of the given instruction format. 226*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE static constexpr size_t SizeInCodeUnits(Format format); 227*795d594fSAndroid Build Coastguard Worker 228*795d594fSAndroid Build Coastguard Worker // Code units required to calculate the size of the instruction. CodeUnitsRequiredForSizeComputation()229*795d594fSAndroid Build Coastguard Worker size_t CodeUnitsRequiredForSizeComputation() const { 230*795d594fSAndroid Build Coastguard Worker const int8_t result = InstructionDescriptorOf(Opcode()).size_in_code_units; 231*795d594fSAndroid Build Coastguard Worker return UNLIKELY(result < 0) ? CodeUnitsRequiredForSizeOfComplexOpcode() : 1; 232*795d594fSAndroid Build Coastguard Worker } 233*795d594fSAndroid Build Coastguard Worker 234*795d594fSAndroid Build Coastguard Worker // Reads an instruction out of the stream at the specified address. At(const uint16_t * code)235*795d594fSAndroid Build Coastguard Worker static const Instruction* At(const uint16_t* code) { 236*795d594fSAndroid Build Coastguard Worker DCHECK(code != nullptr); 237*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const Instruction*>(code); 238*795d594fSAndroid Build Coastguard Worker } 239*795d594fSAndroid Build Coastguard Worker 240*795d594fSAndroid Build Coastguard Worker // Reads an instruction out of the stream from the current address plus an offset. RelativeAt(int32_t offset)241*795d594fSAndroid Build Coastguard Worker const Instruction* RelativeAt(int32_t offset) const WARN_UNUSED { 242*795d594fSAndroid Build Coastguard Worker return At(reinterpret_cast<const uint16_t*>(this) + offset); 243*795d594fSAndroid Build Coastguard Worker } 244*795d594fSAndroid Build Coastguard Worker 245*795d594fSAndroid Build Coastguard Worker // Returns a pointer to the next instruction in the stream. Next()246*795d594fSAndroid Build Coastguard Worker const Instruction* Next() const { 247*795d594fSAndroid Build Coastguard Worker return RelativeAt(SizeInCodeUnits()); 248*795d594fSAndroid Build Coastguard Worker } 249*795d594fSAndroid Build Coastguard Worker 250*795d594fSAndroid Build Coastguard Worker // Returns a pointer to the instruction after this 1xx instruction in the stream. Next_1xx()251*795d594fSAndroid Build Coastguard Worker const Instruction* Next_1xx() const { 252*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t); 253*795d594fSAndroid Build Coastguard Worker return RelativeAt(1); 254*795d594fSAndroid Build Coastguard Worker } 255*795d594fSAndroid Build Coastguard Worker 256*795d594fSAndroid Build Coastguard Worker // Returns a pointer to the instruction after this 2xx instruction in the stream. Next_2xx()257*795d594fSAndroid Build Coastguard Worker const Instruction* Next_2xx() const { 258*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c); 259*795d594fSAndroid Build Coastguard Worker return RelativeAt(2); 260*795d594fSAndroid Build Coastguard Worker } 261*795d594fSAndroid Build Coastguard Worker 262*795d594fSAndroid Build Coastguard Worker // Returns a pointer to the instruction after this 3xx instruction in the stream. Next_3xx()263*795d594fSAndroid Build Coastguard Worker const Instruction* Next_3xx() const { 264*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc); 265*795d594fSAndroid Build Coastguard Worker return RelativeAt(3); 266*795d594fSAndroid Build Coastguard Worker } 267*795d594fSAndroid Build Coastguard Worker 268*795d594fSAndroid Build Coastguard Worker // Returns a pointer to the instruction after this 4xx instruction in the stream. Next_4xx()269*795d594fSAndroid Build Coastguard Worker const Instruction* Next_4xx() const { 270*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) >= k45cc && FormatOf(Opcode()) <= k4rcc); 271*795d594fSAndroid Build Coastguard Worker return RelativeAt(4); 272*795d594fSAndroid Build Coastguard Worker } 273*795d594fSAndroid Build Coastguard Worker 274*795d594fSAndroid Build Coastguard Worker // Returns a pointer to the instruction after this 51l instruction in the stream. Next_51l()275*795d594fSAndroid Build Coastguard Worker const Instruction* Next_51l() const { 276*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k51l); 277*795d594fSAndroid Build Coastguard Worker return RelativeAt(5); 278*795d594fSAndroid Build Coastguard Worker } 279*795d594fSAndroid Build Coastguard Worker 280*795d594fSAndroid Build Coastguard Worker // Returns the name of this instruction's opcode. Name()281*795d594fSAndroid Build Coastguard Worker const char* Name() const { 282*795d594fSAndroid Build Coastguard Worker return Instruction::Name(Opcode()); 283*795d594fSAndroid Build Coastguard Worker } 284*795d594fSAndroid Build Coastguard Worker 285*795d594fSAndroid Build Coastguard Worker // Returns the name of the given opcode. Name(Code opcode)286*795d594fSAndroid Build Coastguard Worker static const char* Name(Code opcode) { 287*795d594fSAndroid Build Coastguard Worker return kInstructionNames[opcode]; 288*795d594fSAndroid Build Coastguard Worker } 289*795d594fSAndroid Build Coastguard Worker 290*795d594fSAndroid Build Coastguard Worker // VRegA 291*795d594fSAndroid Build Coastguard Worker bool HasVRegA() const; 292*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegA() const; 293*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegA(Format format, uint16_t inst_data) const; 294*795d594fSAndroid Build Coastguard Worker VRegA_10t()295*795d594fSAndroid Build Coastguard Worker int8_t VRegA_10t() const { 296*795d594fSAndroid Build Coastguard Worker return VRegA_10t(Fetch16(0)); 297*795d594fSAndroid Build Coastguard Worker } VRegA_10x()298*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_10x() const { 299*795d594fSAndroid Build Coastguard Worker return VRegA_10x(Fetch16(0)); 300*795d594fSAndroid Build Coastguard Worker } VRegA_11n()301*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_11n() const { 302*795d594fSAndroid Build Coastguard Worker return VRegA_11n(Fetch16(0)); 303*795d594fSAndroid Build Coastguard Worker } VRegA_11x()304*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_11x() const { 305*795d594fSAndroid Build Coastguard Worker return VRegA_11x(Fetch16(0)); 306*795d594fSAndroid Build Coastguard Worker } VRegA_12x()307*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_12x() const { 308*795d594fSAndroid Build Coastguard Worker return VRegA_12x(Fetch16(0)); 309*795d594fSAndroid Build Coastguard Worker } 310*795d594fSAndroid Build Coastguard Worker int16_t VRegA_20t() const; VRegA_21c()311*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21c() const { 312*795d594fSAndroid Build Coastguard Worker return VRegA_21c(Fetch16(0)); 313*795d594fSAndroid Build Coastguard Worker } VRegA_21h()314*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21h() const { 315*795d594fSAndroid Build Coastguard Worker return VRegA_21h(Fetch16(0)); 316*795d594fSAndroid Build Coastguard Worker } VRegA_21s()317*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21s() const { 318*795d594fSAndroid Build Coastguard Worker return VRegA_21s(Fetch16(0)); 319*795d594fSAndroid Build Coastguard Worker } VRegA_21t()320*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21t() const { 321*795d594fSAndroid Build Coastguard Worker return VRegA_21t(Fetch16(0)); 322*795d594fSAndroid Build Coastguard Worker } VRegA_22b()323*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_22b() const { 324*795d594fSAndroid Build Coastguard Worker return VRegA_22b(Fetch16(0)); 325*795d594fSAndroid Build Coastguard Worker } VRegA_22c()326*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_22c() const { 327*795d594fSAndroid Build Coastguard Worker return VRegA_22c(Fetch16(0)); 328*795d594fSAndroid Build Coastguard Worker } VRegA_22s()329*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_22s() const { 330*795d594fSAndroid Build Coastguard Worker return VRegA_22s(Fetch16(0)); 331*795d594fSAndroid Build Coastguard Worker } VRegA_22t()332*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_22t() const { 333*795d594fSAndroid Build Coastguard Worker return VRegA_22t(Fetch16(0)); 334*795d594fSAndroid Build Coastguard Worker } VRegA_22x()335*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_22x() const { 336*795d594fSAndroid Build Coastguard Worker return VRegA_22x(Fetch16(0)); 337*795d594fSAndroid Build Coastguard Worker } VRegA_23x()338*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_23x() const { 339*795d594fSAndroid Build Coastguard Worker return VRegA_23x(Fetch16(0)); 340*795d594fSAndroid Build Coastguard Worker } 341*795d594fSAndroid Build Coastguard Worker int32_t VRegA_30t() const; VRegA_31c()342*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_31c() const { 343*795d594fSAndroid Build Coastguard Worker return VRegA_31c(Fetch16(0)); 344*795d594fSAndroid Build Coastguard Worker } VRegA_31i()345*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_31i() const { 346*795d594fSAndroid Build Coastguard Worker return VRegA_31i(Fetch16(0)); 347*795d594fSAndroid Build Coastguard Worker } VRegA_31t()348*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_31t() const { 349*795d594fSAndroid Build Coastguard Worker return VRegA_31t(Fetch16(0)); 350*795d594fSAndroid Build Coastguard Worker } 351*795d594fSAndroid Build Coastguard Worker uint16_t VRegA_32x() const; VRegA_35c()352*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_35c() const { 353*795d594fSAndroid Build Coastguard Worker return VRegA_35c(Fetch16(0)); 354*795d594fSAndroid Build Coastguard Worker } VRegA_3rc()355*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_3rc() const { 356*795d594fSAndroid Build Coastguard Worker return VRegA_3rc(Fetch16(0)); 357*795d594fSAndroid Build Coastguard Worker } VRegA_51l()358*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_51l() const { 359*795d594fSAndroid Build Coastguard Worker return VRegA_51l(Fetch16(0)); 360*795d594fSAndroid Build Coastguard Worker } VRegA_45cc()361*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_45cc() const { 362*795d594fSAndroid Build Coastguard Worker return VRegA_45cc(Fetch16(0)); 363*795d594fSAndroid Build Coastguard Worker } VRegA_4rcc()364*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_4rcc() const { 365*795d594fSAndroid Build Coastguard Worker return VRegA_4rcc(Fetch16(0)); 366*795d594fSAndroid Build Coastguard Worker } 367*795d594fSAndroid Build Coastguard Worker 368*795d594fSAndroid Build Coastguard Worker // The following methods return the vA operand for various instruction formats. The "inst_data" 369*795d594fSAndroid Build Coastguard Worker // parameter holds the first 16 bits of instruction which the returned value is decoded from. 370*795d594fSAndroid Build Coastguard Worker int8_t VRegA_10t(uint16_t inst_data) const; 371*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_10x(uint16_t inst_data) const; 372*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_11n(uint16_t inst_data) const; 373*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_11x(uint16_t inst_data) const; 374*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_12x(uint16_t inst_data) const; 375*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21c(uint16_t inst_data) const; 376*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21h(uint16_t inst_data) const; 377*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21s(uint16_t inst_data) const; 378*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_21t(uint16_t inst_data) const; 379*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_22b(uint16_t inst_data) const; 380*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_22c(uint16_t inst_data) const; 381*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_22s(uint16_t inst_data) const; 382*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_22t(uint16_t inst_data) const; 383*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_22x(uint16_t inst_data) const; 384*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_23x(uint16_t inst_data) const; 385*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_31c(uint16_t inst_data) const; 386*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_31i(uint16_t inst_data) const; 387*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_31t(uint16_t inst_data) const; 388*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_35c(uint16_t inst_data) const; 389*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_3rc(uint16_t inst_data) const; 390*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_51l(uint16_t inst_data) const; 391*795d594fSAndroid Build Coastguard Worker uint4_t VRegA_45cc(uint16_t inst_data) const; 392*795d594fSAndroid Build Coastguard Worker uint8_t VRegA_4rcc(uint16_t inst_data) const; 393*795d594fSAndroid Build Coastguard Worker 394*795d594fSAndroid Build Coastguard Worker // VRegB 395*795d594fSAndroid Build Coastguard Worker bool HasVRegB() const; 396*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegB() const; 397*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegB(Format format, uint16_t inst_data) const; 398*795d594fSAndroid Build Coastguard Worker 399*795d594fSAndroid Build Coastguard Worker bool HasWideVRegB() const; 400*795d594fSAndroid Build Coastguard Worker uint64_t WideVRegB() const; 401*795d594fSAndroid Build Coastguard Worker VRegB_11n()402*795d594fSAndroid Build Coastguard Worker int4_t VRegB_11n() const { 403*795d594fSAndroid Build Coastguard Worker return VRegB_11n(Fetch16(0)); 404*795d594fSAndroid Build Coastguard Worker } VRegB_12x()405*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_12x() const { 406*795d594fSAndroid Build Coastguard Worker return VRegB_12x(Fetch16(0)); 407*795d594fSAndroid Build Coastguard Worker } 408*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_21c() const; 409*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_21h() const; 410*795d594fSAndroid Build Coastguard Worker int16_t VRegB_21s() const; 411*795d594fSAndroid Build Coastguard Worker int16_t VRegB_21t() const; 412*795d594fSAndroid Build Coastguard Worker uint8_t VRegB_22b() const; VRegB_22c()413*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_22c() const { 414*795d594fSAndroid Build Coastguard Worker return VRegB_22c(Fetch16(0)); 415*795d594fSAndroid Build Coastguard Worker } VRegB_22s()416*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_22s() const { 417*795d594fSAndroid Build Coastguard Worker return VRegB_22s(Fetch16(0)); 418*795d594fSAndroid Build Coastguard Worker } VRegB_22t()419*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_22t() const { 420*795d594fSAndroid Build Coastguard Worker return VRegB_22t(Fetch16(0)); 421*795d594fSAndroid Build Coastguard Worker } 422*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_22x() const; 423*795d594fSAndroid Build Coastguard Worker uint8_t VRegB_23x() const; 424*795d594fSAndroid Build Coastguard Worker uint32_t VRegB_31c() const; 425*795d594fSAndroid Build Coastguard Worker int32_t VRegB_31i() const; 426*795d594fSAndroid Build Coastguard Worker int32_t VRegB_31t() const; 427*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_32x() const; 428*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_35c() const; 429*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_3rc() const; 430*795d594fSAndroid Build Coastguard Worker uint64_t VRegB_51l() const; // vB_wide 431*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_45cc() const; 432*795d594fSAndroid Build Coastguard Worker uint16_t VRegB_4rcc() const; 433*795d594fSAndroid Build Coastguard Worker 434*795d594fSAndroid Build Coastguard Worker // The following methods return the vB operand for all instruction formats where it is encoded in 435*795d594fSAndroid Build Coastguard Worker // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned 436*795d594fSAndroid Build Coastguard Worker // value is decoded from it. 437*795d594fSAndroid Build Coastguard Worker int4_t VRegB_11n(uint16_t inst_data) const; 438*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_12x(uint16_t inst_data) const; 439*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_22c(uint16_t inst_data) const; 440*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_22s(uint16_t inst_data) const; 441*795d594fSAndroid Build Coastguard Worker uint4_t VRegB_22t(uint16_t inst_data) const; 442*795d594fSAndroid Build Coastguard Worker 443*795d594fSAndroid Build Coastguard Worker // VRegC 444*795d594fSAndroid Build Coastguard Worker bool HasVRegC() const; 445*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegC() const; 446*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegC(Format format) const; 447*795d594fSAndroid Build Coastguard Worker 448*795d594fSAndroid Build Coastguard Worker int8_t VRegC_22b() const; 449*795d594fSAndroid Build Coastguard Worker uint16_t VRegC_22c() const; 450*795d594fSAndroid Build Coastguard Worker int16_t VRegC_22s() const; 451*795d594fSAndroid Build Coastguard Worker int16_t VRegC_22t() const; 452*795d594fSAndroid Build Coastguard Worker uint8_t VRegC_23x() const; 453*795d594fSAndroid Build Coastguard Worker uint4_t VRegC_35c() const; 454*795d594fSAndroid Build Coastguard Worker uint16_t VRegC_3rc() const; 455*795d594fSAndroid Build Coastguard Worker uint4_t VRegC_45cc() const; 456*795d594fSAndroid Build Coastguard Worker uint16_t VRegC_4rcc() const; 457*795d594fSAndroid Build Coastguard Worker 458*795d594fSAndroid Build Coastguard Worker 459*795d594fSAndroid Build Coastguard Worker // VRegH 460*795d594fSAndroid Build Coastguard Worker bool HasVRegH() const; 461*795d594fSAndroid Build Coastguard Worker int32_t VRegH() const; 462*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE int32_t VRegH(Format format) const; 463*795d594fSAndroid Build Coastguard Worker uint16_t VRegH_45cc() const; 464*795d594fSAndroid Build Coastguard Worker uint16_t VRegH_4rcc() const; 465*795d594fSAndroid Build Coastguard Worker 466*795d594fSAndroid Build Coastguard Worker // Fills the given array with the 'arg' array of the instruction. 467*795d594fSAndroid Build Coastguard Worker bool HasVarArgs() const; 468*795d594fSAndroid Build Coastguard Worker uint32_t GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const; GetVarArgs(uint32_t args[kMaxVarArgRegs])469*795d594fSAndroid Build Coastguard Worker uint32_t GetVarArgs(uint32_t args[kMaxVarArgRegs]) const { 470*795d594fSAndroid Build Coastguard Worker return GetVarArgs(args, Fetch16(0)); 471*795d594fSAndroid Build Coastguard Worker } 472*795d594fSAndroid Build Coastguard Worker 473*795d594fSAndroid Build Coastguard Worker // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first 474*795d594fSAndroid Build Coastguard Worker // 16 bits of instruction. Opcode(uint16_t inst_data)475*795d594fSAndroid Build Coastguard Worker Code Opcode(uint16_t inst_data) const { 476*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(inst_data, Fetch16(0)); 477*795d594fSAndroid Build Coastguard Worker return static_cast<Code>(inst_data & 0xFF); 478*795d594fSAndroid Build Coastguard Worker } 479*795d594fSAndroid Build Coastguard Worker 480*795d594fSAndroid Build Coastguard Worker // Returns the opcode field of the instruction from the first 16 bits of instruction. Opcode()481*795d594fSAndroid Build Coastguard Worker Code Opcode() const { 482*795d594fSAndroid Build Coastguard Worker return Opcode(Fetch16(0)); 483*795d594fSAndroid Build Coastguard Worker } 484*795d594fSAndroid Build Coastguard Worker SetOpcode(Code opcode)485*795d594fSAndroid Build Coastguard Worker void SetOpcode(Code opcode) { 486*795d594fSAndroid Build Coastguard Worker DCHECK_LT(static_cast<uint16_t>(opcode), 256u); 487*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 488*795d594fSAndroid Build Coastguard Worker insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode); 489*795d594fSAndroid Build Coastguard Worker } 490*795d594fSAndroid Build Coastguard Worker SetVRegA_10x(uint8_t val)491*795d594fSAndroid Build Coastguard Worker void SetVRegA_10x(uint8_t val) { 492*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k10x); 493*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 494*795d594fSAndroid Build Coastguard Worker insns[0] = (val << 8) | (insns[0] & 0x00ff); 495*795d594fSAndroid Build Coastguard Worker } 496*795d594fSAndroid Build Coastguard Worker SetVRegB_3rc(uint16_t val)497*795d594fSAndroid Build Coastguard Worker void SetVRegB_3rc(uint16_t val) { 498*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k3rc); 499*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 500*795d594fSAndroid Build Coastguard Worker insns[1] = val; 501*795d594fSAndroid Build Coastguard Worker } 502*795d594fSAndroid Build Coastguard Worker SetVRegB_35c(uint16_t val)503*795d594fSAndroid Build Coastguard Worker void SetVRegB_35c(uint16_t val) { 504*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k35c); 505*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 506*795d594fSAndroid Build Coastguard Worker insns[1] = val; 507*795d594fSAndroid Build Coastguard Worker } 508*795d594fSAndroid Build Coastguard Worker SetVRegC_22c(uint16_t val)509*795d594fSAndroid Build Coastguard Worker void SetVRegC_22c(uint16_t val) { 510*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k22c); 511*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 512*795d594fSAndroid Build Coastguard Worker insns[1] = val; 513*795d594fSAndroid Build Coastguard Worker } 514*795d594fSAndroid Build Coastguard Worker SetVRegA_21c(uint8_t val)515*795d594fSAndroid Build Coastguard Worker void SetVRegA_21c(uint8_t val) { 516*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k21c); 517*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 518*795d594fSAndroid Build Coastguard Worker insns[0] = (val << 8) | (insns[0] & 0x00ff); 519*795d594fSAndroid Build Coastguard Worker } 520*795d594fSAndroid Build Coastguard Worker SetVRegB_21c(uint16_t val)521*795d594fSAndroid Build Coastguard Worker void SetVRegB_21c(uint16_t val) { 522*795d594fSAndroid Build Coastguard Worker DCHECK(FormatOf(Opcode()) == k21c); 523*795d594fSAndroid Build Coastguard Worker uint16_t* insns = reinterpret_cast<uint16_t*>(this); 524*795d594fSAndroid Build Coastguard Worker insns[1] = val; 525*795d594fSAndroid Build Coastguard Worker } 526*795d594fSAndroid Build Coastguard Worker 527*795d594fSAndroid Build Coastguard Worker // Returns the format of the given opcode. FormatOf(Code opcode)528*795d594fSAndroid Build Coastguard Worker static constexpr Format FormatOf(Code opcode) { 529*795d594fSAndroid Build Coastguard Worker return InstructionDescriptorOf(opcode).format; 530*795d594fSAndroid Build Coastguard Worker } 531*795d594fSAndroid Build Coastguard Worker 532*795d594fSAndroid Build Coastguard Worker // Returns the index type of the given opcode. IndexTypeOf(Code opcode)533*795d594fSAndroid Build Coastguard Worker static constexpr IndexType IndexTypeOf(Code opcode) { 534*795d594fSAndroid Build Coastguard Worker return InstructionDescriptorOf(opcode).index_type; 535*795d594fSAndroid Build Coastguard Worker } 536*795d594fSAndroid Build Coastguard Worker 537*795d594fSAndroid Build Coastguard Worker // Returns the flags for the given opcode. FlagsOf(Code opcode)538*795d594fSAndroid Build Coastguard Worker static constexpr uint8_t FlagsOf(Code opcode) { 539*795d594fSAndroid Build Coastguard Worker return InstructionDescriptorOf(opcode).flags; 540*795d594fSAndroid Build Coastguard Worker } 541*795d594fSAndroid Build Coastguard Worker 542*795d594fSAndroid Build Coastguard Worker // Return the verify flags for the given opcode. VerifyFlagsOf(Code opcode)543*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t VerifyFlagsOf(Code opcode) { 544*795d594fSAndroid Build Coastguard Worker return InstructionDescriptorOf(opcode).verify_flags; 545*795d594fSAndroid Build Coastguard Worker } 546*795d594fSAndroid Build Coastguard Worker 547*795d594fSAndroid Build Coastguard Worker // Returns true if this instruction is a branch. IsBranch()548*795d594fSAndroid Build Coastguard Worker bool IsBranch() const { 549*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(Opcode()).flags & kBranch) != 0; 550*795d594fSAndroid Build Coastguard Worker } 551*795d594fSAndroid Build Coastguard Worker 552*795d594fSAndroid Build Coastguard Worker // Returns true if this instruction is a unconditional branch. IsUnconditional()553*795d594fSAndroid Build Coastguard Worker bool IsUnconditional() const { 554*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(Opcode()).flags & kUnconditional) != 0; 555*795d594fSAndroid Build Coastguard Worker } 556*795d594fSAndroid Build Coastguard Worker 557*795d594fSAndroid Build Coastguard Worker // Returns the branch offset if this instruction is a branch. 558*795d594fSAndroid Build Coastguard Worker int32_t GetTargetOffset() const; 559*795d594fSAndroid Build Coastguard Worker 560*795d594fSAndroid Build Coastguard Worker // Returns true if the instruction allows control flow to go to the following instruction. 561*795d594fSAndroid Build Coastguard Worker bool CanFlowThrough() const; 562*795d594fSAndroid Build Coastguard Worker 563*795d594fSAndroid Build Coastguard Worker // Returns true if this instruction is a switch. IsSwitch()564*795d594fSAndroid Build Coastguard Worker bool IsSwitch() const { 565*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(Opcode()).flags & kSwitch) != 0; 566*795d594fSAndroid Build Coastguard Worker } 567*795d594fSAndroid Build Coastguard Worker 568*795d594fSAndroid Build Coastguard Worker // Returns true if this instruction can throw. IsThrow()569*795d594fSAndroid Build Coastguard Worker bool IsThrow() const { 570*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(Opcode()).flags & kThrow) != 0; 571*795d594fSAndroid Build Coastguard Worker } 572*795d594fSAndroid Build Coastguard Worker 573*795d594fSAndroid Build Coastguard Worker // Determine if the instruction is any of 'return' instructions. IsReturn(Code opcode)574*795d594fSAndroid Build Coastguard Worker static constexpr bool IsReturn(Code opcode) { 575*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(opcode).flags & kReturn) != 0; 576*795d594fSAndroid Build Coastguard Worker } IsReturn()577*795d594fSAndroid Build Coastguard Worker bool IsReturn() const { 578*795d594fSAndroid Build Coastguard Worker return IsReturn(Opcode()); 579*795d594fSAndroid Build Coastguard Worker } 580*795d594fSAndroid Build Coastguard Worker 581*795d594fSAndroid Build Coastguard Worker // Determine if this instruction ends execution of its basic block. IsBasicBlockEnd()582*795d594fSAndroid Build Coastguard Worker bool IsBasicBlockEnd() const { 583*795d594fSAndroid Build Coastguard Worker return IsBranch() || IsReturn() || Opcode() == THROW; 584*795d594fSAndroid Build Coastguard Worker } 585*795d594fSAndroid Build Coastguard Worker 586*795d594fSAndroid Build Coastguard Worker // Determine if this instruction is an invoke. IsInvoke()587*795d594fSAndroid Build Coastguard Worker bool IsInvoke() const { 588*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(Opcode()).flags & kInvoke) != 0; 589*795d594fSAndroid Build Coastguard Worker } 590*795d594fSAndroid Build Coastguard Worker 591*795d594fSAndroid Build Coastguard Worker // Determine if this instruction is experimental. IsExperimental()592*795d594fSAndroid Build Coastguard Worker bool IsExperimental() const { 593*795d594fSAndroid Build Coastguard Worker return (InstructionDescriptorOf(Opcode()).flags & kExperimental) != 0; 594*795d594fSAndroid Build Coastguard Worker } 595*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentAOf(Code opcode)596*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t GetVerifyTypeArgumentAOf(Code opcode) { 597*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kMask = kVerifyRegA | kVerifyRegAWide; 598*795d594fSAndroid Build Coastguard Worker return VerifyFlagsOf(opcode) & kMask; 599*795d594fSAndroid Build Coastguard Worker } 600*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentA()601*795d594fSAndroid Build Coastguard Worker uint32_t GetVerifyTypeArgumentA() const { 602*795d594fSAndroid Build Coastguard Worker return GetVerifyTypeArgumentAOf(Opcode()); 603*795d594fSAndroid Build Coastguard Worker } 604*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentBOf(Code opcode)605*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t GetVerifyTypeArgumentBOf(Code opcode) { 606*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kMask = 607*795d594fSAndroid Build Coastguard Worker kVerifyRegB | 608*795d594fSAndroid Build Coastguard Worker kVerifyRegBField | 609*795d594fSAndroid Build Coastguard Worker kVerifyRegBMethod | 610*795d594fSAndroid Build Coastguard Worker kVerifyRegBNewInstance | 611*795d594fSAndroid Build Coastguard Worker kVerifyRegBString | 612*795d594fSAndroid Build Coastguard Worker kVerifyRegBType | 613*795d594fSAndroid Build Coastguard Worker kVerifyRegBWide; 614*795d594fSAndroid Build Coastguard Worker return VerifyFlagsOf(opcode) & kMask; 615*795d594fSAndroid Build Coastguard Worker } 616*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentB()617*795d594fSAndroid Build Coastguard Worker uint32_t GetVerifyTypeArgumentB() const { 618*795d594fSAndroid Build Coastguard Worker return GetVerifyTypeArgumentBOf(Opcode()); 619*795d594fSAndroid Build Coastguard Worker } 620*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentCOf(Code opcode)621*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t GetVerifyTypeArgumentCOf(Code opcode) { 622*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kMask = 623*795d594fSAndroid Build Coastguard Worker kVerifyRegC | kVerifyRegCField | kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide; 624*795d594fSAndroid Build Coastguard Worker return VerifyFlagsOf(opcode) & kMask; 625*795d594fSAndroid Build Coastguard Worker } 626*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentC()627*795d594fSAndroid Build Coastguard Worker uint32_t GetVerifyTypeArgumentC() const { 628*795d594fSAndroid Build Coastguard Worker return GetVerifyTypeArgumentCOf(Opcode()); 629*795d594fSAndroid Build Coastguard Worker } 630*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentHOf(Code opcode)631*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t GetVerifyTypeArgumentHOf(Code opcode) { 632*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kMask = kVerifyRegHPrototype; 633*795d594fSAndroid Build Coastguard Worker return VerifyFlagsOf(opcode) & kMask; 634*795d594fSAndroid Build Coastguard Worker } 635*795d594fSAndroid Build Coastguard Worker GetVerifyTypeArgumentH()636*795d594fSAndroid Build Coastguard Worker uint32_t GetVerifyTypeArgumentH() const { 637*795d594fSAndroid Build Coastguard Worker return GetVerifyTypeArgumentHOf(Opcode()); 638*795d594fSAndroid Build Coastguard Worker } 639*795d594fSAndroid Build Coastguard Worker GetVerifyExtraFlagsOf(Code opcode)640*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t GetVerifyExtraFlagsOf(Code opcode) { 641*795d594fSAndroid Build Coastguard Worker constexpr uint32_t kMask = 642*795d594fSAndroid Build Coastguard Worker kVerifyArrayData | 643*795d594fSAndroid Build Coastguard Worker kVerifyBranchTarget | 644*795d594fSAndroid Build Coastguard Worker kVerifySwitchTargets | 645*795d594fSAndroid Build Coastguard Worker kVerifyVarArg | 646*795d594fSAndroid Build Coastguard Worker kVerifyVarArgNonZero | 647*795d594fSAndroid Build Coastguard Worker kVerifyVarArgRange | 648*795d594fSAndroid Build Coastguard Worker kVerifyVarArgRangeNonZero | 649*795d594fSAndroid Build Coastguard Worker kVerifyError; 650*795d594fSAndroid Build Coastguard Worker return VerifyFlagsOf(opcode) & kMask; 651*795d594fSAndroid Build Coastguard Worker } 652*795d594fSAndroid Build Coastguard Worker GetVerifyExtraFlags()653*795d594fSAndroid Build Coastguard Worker uint32_t GetVerifyExtraFlags() const { 654*795d594fSAndroid Build Coastguard Worker return GetVerifyExtraFlagsOf(Opcode()); 655*795d594fSAndroid Build Coastguard Worker } 656*795d594fSAndroid Build Coastguard Worker 657*795d594fSAndroid Build Coastguard Worker // Get the dex PC of this instruction as a offset in code units from the beginning of insns. GetDexPc(const uint16_t * insns)658*795d594fSAndroid Build Coastguard Worker uint32_t GetDexPc(const uint16_t* insns) const { 659*795d594fSAndroid Build Coastguard Worker return (reinterpret_cast<const uint16_t*>(this) - insns); 660*795d594fSAndroid Build Coastguard Worker } 661*795d594fSAndroid Build Coastguard Worker 662*795d594fSAndroid Build Coastguard Worker // Dump decoded version of instruction 663*795d594fSAndroid Build Coastguard Worker std::string DumpString(const DexFile*) const; 664*795d594fSAndroid Build Coastguard Worker 665*795d594fSAndroid Build Coastguard Worker // Dump code_units worth of this instruction, padding to code_units for shorter instructions 666*795d594fSAndroid Build Coastguard Worker std::string DumpHex(size_t code_units) const; 667*795d594fSAndroid Build Coastguard Worker 668*795d594fSAndroid Build Coastguard Worker // Little-endian dump code_units worth of this instruction, padding to code_units for 669*795d594fSAndroid Build Coastguard Worker // shorter instructions 670*795d594fSAndroid Build Coastguard Worker std::string DumpHexLE(size_t instr_code_units) const; 671*795d594fSAndroid Build Coastguard Worker Fetch16(size_t offset)672*795d594fSAndroid Build Coastguard Worker uint16_t Fetch16(size_t offset) const { 673*795d594fSAndroid Build Coastguard Worker const uint16_t* insns = reinterpret_cast<const uint16_t*>(this); 674*795d594fSAndroid Build Coastguard Worker return insns[offset]; 675*795d594fSAndroid Build Coastguard Worker } 676*795d594fSAndroid Build Coastguard Worker 677*795d594fSAndroid Build Coastguard Worker size_t SizeInCodeUnitsComplexOpcode() const; 678*795d594fSAndroid Build Coastguard Worker 679*795d594fSAndroid Build Coastguard Worker private: InstructionDescriptorOf(Code opcode)680*795d594fSAndroid Build Coastguard Worker static constexpr const InstructionDescriptor& InstructionDescriptorOf(Code opcode) { 681*795d594fSAndroid Build Coastguard Worker return kInstructionDescriptors[opcode]; 682*795d594fSAndroid Build Coastguard Worker } 683*795d594fSAndroid Build Coastguard Worker 684*795d594fSAndroid Build Coastguard Worker // Return how many code unit words are required to compute the size of the opcode. 685*795d594fSAndroid Build Coastguard Worker size_t CodeUnitsRequiredForSizeOfComplexOpcode() const; 686*795d594fSAndroid Build Coastguard Worker Fetch32(size_t offset)687*795d594fSAndroid Build Coastguard Worker uint32_t Fetch32(size_t offset) const { 688*795d594fSAndroid Build Coastguard Worker return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16)); 689*795d594fSAndroid Build Coastguard Worker } 690*795d594fSAndroid Build Coastguard Worker InstA()691*795d594fSAndroid Build Coastguard Worker uint4_t InstA() const { 692*795d594fSAndroid Build Coastguard Worker return InstA(Fetch16(0)); 693*795d594fSAndroid Build Coastguard Worker } 694*795d594fSAndroid Build Coastguard Worker InstB()695*795d594fSAndroid Build Coastguard Worker uint4_t InstB() const { 696*795d594fSAndroid Build Coastguard Worker return InstB(Fetch16(0)); 697*795d594fSAndroid Build Coastguard Worker } 698*795d594fSAndroid Build Coastguard Worker InstAA()699*795d594fSAndroid Build Coastguard Worker uint8_t InstAA() const { 700*795d594fSAndroid Build Coastguard Worker return InstAA(Fetch16(0)); 701*795d594fSAndroid Build Coastguard Worker } 702*795d594fSAndroid Build Coastguard Worker InstA(uint16_t inst_data)703*795d594fSAndroid Build Coastguard Worker uint4_t InstA(uint16_t inst_data) const { 704*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(inst_data, Fetch16(0)); 705*795d594fSAndroid Build Coastguard Worker return static_cast<uint4_t>((inst_data >> 8) & 0x0f); 706*795d594fSAndroid Build Coastguard Worker } 707*795d594fSAndroid Build Coastguard Worker InstB(uint16_t inst_data)708*795d594fSAndroid Build Coastguard Worker uint4_t InstB(uint16_t inst_data) const { 709*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(inst_data, Fetch16(0)); 710*795d594fSAndroid Build Coastguard Worker return static_cast<uint4_t>(inst_data >> 12); 711*795d594fSAndroid Build Coastguard Worker } 712*795d594fSAndroid Build Coastguard Worker InstAA(uint16_t inst_data)713*795d594fSAndroid Build Coastguard Worker uint8_t InstAA(uint16_t inst_data) const { 714*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(inst_data, Fetch16(0)); 715*795d594fSAndroid Build Coastguard Worker return static_cast<uint8_t>(inst_data >> 8); 716*795d594fSAndroid Build Coastguard Worker } 717*795d594fSAndroid Build Coastguard Worker 718*795d594fSAndroid Build Coastguard Worker static const char* const kInstructionNames[]; 719*795d594fSAndroid Build Coastguard Worker 720*795d594fSAndroid Build Coastguard Worker static constexpr std::array<InstructionDescriptor, 256> kInstructionDescriptors = []() constexpr { 721*795d594fSAndroid Build Coastguard Worker auto InstructionSizeInCodeUnitsByOpcode = [](Instruction::Code opcode, 722*795d594fSAndroid Build Coastguard Worker Instruction::Format format) constexpr -> int8_t { 723*795d594fSAndroid Build Coastguard Worker if (opcode == Instruction::Code::NOP) { 724*795d594fSAndroid Build Coastguard Worker return -1; 725*795d594fSAndroid Build Coastguard Worker } else if ((format >= Instruction::Format::k10x) && (format <= Instruction::Format::k10t)) { 726*795d594fSAndroid Build Coastguard Worker return 1; 727*795d594fSAndroid Build Coastguard Worker } else if ((format >= Instruction::Format::k20t) && (format <= Instruction::Format::k22c)) { 728*795d594fSAndroid Build Coastguard Worker return 2; 729*795d594fSAndroid Build Coastguard Worker } else if ((format >= Instruction::Format::k32x) && (format <= Instruction::Format::k3rc)) { 730*795d594fSAndroid Build Coastguard Worker return 3; 731*795d594fSAndroid Build Coastguard Worker } else if ((format >= Instruction::Format::k45cc) && (format <= Instruction::Format::k4rcc)) { 732*795d594fSAndroid Build Coastguard Worker return 4; 733*795d594fSAndroid Build Coastguard Worker } else if (format == Instruction::Format::k51l) { 734*795d594fSAndroid Build Coastguard Worker return 5; 735*795d594fSAndroid Build Coastguard Worker } else { 736*795d594fSAndroid Build Coastguard Worker return -1; 737*795d594fSAndroid Build Coastguard Worker } 738*795d594fSAndroid Build Coastguard Worker }; 739*795d594fSAndroid Build Coastguard Worker 740*795d594fSAndroid Build Coastguard Worker std::array<InstructionDescriptor, 256> result; 741*795d594fSAndroid Build Coastguard Worker #define INSTRUCTION_DESCR(opcode, c, p, format, index, flags, eflags, vflags) \ 742*795d594fSAndroid Build Coastguard Worker result[opcode] = { \ 743*795d594fSAndroid Build Coastguard Worker vflags, \ 744*795d594fSAndroid Build Coastguard Worker format, \ 745*795d594fSAndroid Build Coastguard Worker index, \ 746*795d594fSAndroid Build Coastguard Worker flags, \ 747*795d594fSAndroid Build Coastguard Worker InstructionSizeInCodeUnitsByOpcode((c), (format)), \ 748*795d594fSAndroid Build Coastguard Worker }; 749*795d594fSAndroid Build Coastguard Worker DEX_INSTRUCTION_LIST(INSTRUCTION_DESCR) 750*795d594fSAndroid Build Coastguard Worker #undef INSTRUCTION_DESCR 751*795d594fSAndroid Build Coastguard Worker return result; 752*795d594fSAndroid Build Coastguard Worker }(); 753*795d594fSAndroid Build Coastguard Worker 754*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); 755*795d594fSAndroid Build Coastguard Worker }; 756*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, Instruction::Code code); 757*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, Instruction::Format format); 758*795d594fSAndroid Build Coastguard Worker 759*795d594fSAndroid Build Coastguard Worker // Base class for accessing instruction operands. Unifies operand 760*795d594fSAndroid Build Coastguard Worker // access for instructions that have range and varargs forms 761*795d594fSAndroid Build Coastguard Worker // (e.g. invoke-polymoprhic/range and invoke-polymorphic). 762*795d594fSAndroid Build Coastguard Worker class InstructionOperands { 763*795d594fSAndroid Build Coastguard Worker public: InstructionOperands(size_t num_operands)764*795d594fSAndroid Build Coastguard Worker explicit InstructionOperands(size_t num_operands) : num_operands_(num_operands) {} ~InstructionOperands()765*795d594fSAndroid Build Coastguard Worker virtual ~InstructionOperands() {} 766*795d594fSAndroid Build Coastguard Worker virtual uint32_t GetOperand(size_t index) const = 0; GetNumberOfOperands()767*795d594fSAndroid Build Coastguard Worker size_t GetNumberOfOperands() const { return num_operands_; } 768*795d594fSAndroid Build Coastguard Worker 769*795d594fSAndroid Build Coastguard Worker private: 770*795d594fSAndroid Build Coastguard Worker const size_t num_operands_; 771*795d594fSAndroid Build Coastguard Worker 772*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(InstructionOperands); 773*795d594fSAndroid Build Coastguard Worker }; 774*795d594fSAndroid Build Coastguard Worker 775*795d594fSAndroid Build Coastguard Worker // Class for accessing operands for instructions with a range format 776*795d594fSAndroid Build Coastguard Worker // (e.g. 3rc and 4rcc). 777*795d594fSAndroid Build Coastguard Worker class RangeInstructionOperands final : public InstructionOperands { 778*795d594fSAndroid Build Coastguard Worker public: RangeInstructionOperands(uint32_t first_operand,size_t num_operands)779*795d594fSAndroid Build Coastguard Worker RangeInstructionOperands(uint32_t first_operand, size_t num_operands) 780*795d594fSAndroid Build Coastguard Worker : InstructionOperands(num_operands), first_operand_(first_operand) {} ~RangeInstructionOperands()781*795d594fSAndroid Build Coastguard Worker ~RangeInstructionOperands() {} 782*795d594fSAndroid Build Coastguard Worker uint32_t GetOperand(size_t operand_index) const override; 783*795d594fSAndroid Build Coastguard Worker 784*795d594fSAndroid Build Coastguard Worker private: 785*795d594fSAndroid Build Coastguard Worker const uint32_t first_operand_; 786*795d594fSAndroid Build Coastguard Worker 787*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(RangeInstructionOperands); 788*795d594fSAndroid Build Coastguard Worker }; 789*795d594fSAndroid Build Coastguard Worker 790*795d594fSAndroid Build Coastguard Worker // Class for accessing operands for instructions with a variable 791*795d594fSAndroid Build Coastguard Worker // number of arguments format (e.g. 35c and 45cc). 792*795d594fSAndroid Build Coastguard Worker class VarArgsInstructionOperands final : public InstructionOperands { 793*795d594fSAndroid Build Coastguard Worker public: VarArgsInstructionOperands(const uint32_t (& operands)[Instruction::kMaxVarArgRegs],size_t num_operands)794*795d594fSAndroid Build Coastguard Worker VarArgsInstructionOperands(const uint32_t (&operands)[Instruction::kMaxVarArgRegs], 795*795d594fSAndroid Build Coastguard Worker size_t num_operands) 796*795d594fSAndroid Build Coastguard Worker : InstructionOperands(num_operands), operands_(operands) {} ~VarArgsInstructionOperands()797*795d594fSAndroid Build Coastguard Worker ~VarArgsInstructionOperands() {} 798*795d594fSAndroid Build Coastguard Worker uint32_t GetOperand(size_t operand_index) const override; 799*795d594fSAndroid Build Coastguard Worker 800*795d594fSAndroid Build Coastguard Worker private: 801*795d594fSAndroid Build Coastguard Worker const uint32_t (&operands_)[Instruction::kMaxVarArgRegs]; 802*795d594fSAndroid Build Coastguard Worker 803*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(VarArgsInstructionOperands); 804*795d594fSAndroid Build Coastguard Worker }; 805*795d594fSAndroid Build Coastguard Worker 806*795d594fSAndroid Build Coastguard Worker // Class for accessing operands without the receiver by wrapping an 807*795d594fSAndroid Build Coastguard Worker // existing InstructionOperands instance. 808*795d594fSAndroid Build Coastguard Worker class NoReceiverInstructionOperands final : public InstructionOperands { 809*795d594fSAndroid Build Coastguard Worker public: NoReceiverInstructionOperands(const InstructionOperands * const inner)810*795d594fSAndroid Build Coastguard Worker explicit NoReceiverInstructionOperands(const InstructionOperands* const inner) 811*795d594fSAndroid Build Coastguard Worker : InstructionOperands(inner->GetNumberOfOperands() - 1), inner_(inner) {} ~NoReceiverInstructionOperands()812*795d594fSAndroid Build Coastguard Worker ~NoReceiverInstructionOperands() {} 813*795d594fSAndroid Build Coastguard Worker uint32_t GetOperand(size_t operand_index) const override; 814*795d594fSAndroid Build Coastguard Worker 815*795d594fSAndroid Build Coastguard Worker private: 816*795d594fSAndroid Build Coastguard Worker const InstructionOperands* const inner_; 817*795d594fSAndroid Build Coastguard Worker 818*795d594fSAndroid Build Coastguard Worker DISALLOW_IMPLICIT_CONSTRUCTORS(NoReceiverInstructionOperands); 819*795d594fSAndroid Build Coastguard Worker }; 820*795d594fSAndroid Build Coastguard Worker 821*795d594fSAndroid Build Coastguard Worker } // namespace art 822*795d594fSAndroid Build Coastguard Worker 823*795d594fSAndroid Build Coastguard Worker #endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_ 824