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