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:
GetKeysSparseSwitchPayload60     const int32_t* GetKeys() const {
61       return keys_and_targets;
62     }
63 
GetTargetsSparseSwitchPayload64     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.
SizeInCodeUnits()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.
At(const uint16_t * code)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.
RelativeAt(int32_t 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.
Next()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.
Next_1xx()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.
Next_2xx()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.
Next_3xx()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.
Next_51l()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.
Name()241   const char* Name() const {
242     return Instruction::Name(Opcode());
243   }
244 
245   // Returns the name of the given opcode.
Name(Code 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 
VRegA_10t()254   int8_t VRegA_10t() const {
255     return VRegA_10t(Fetch16(0));
256   }
VRegA_10x()257   uint8_t VRegA_10x() const {
258     return VRegA_10x(Fetch16(0));
259   }
VRegA_11n()260   uint4_t VRegA_11n() const {
261     return VRegA_11n(Fetch16(0));
262   }
VRegA_11x()263   uint8_t VRegA_11x() const {
264     return VRegA_11x(Fetch16(0));
265   }
VRegA_12x()266   uint4_t VRegA_12x() const {
267     return VRegA_12x(Fetch16(0));
268   }
269   int16_t VRegA_20t() const;
VRegA_21c()270   uint8_t VRegA_21c() const {
271     return VRegA_21c(Fetch16(0));
272   }
VRegA_21h()273   uint8_t VRegA_21h() const {
274     return VRegA_21h(Fetch16(0));
275   }
VRegA_21s()276   uint8_t VRegA_21s() const {
277     return VRegA_21s(Fetch16(0));
278   }
VRegA_21t()279   uint8_t VRegA_21t() const {
280     return VRegA_21t(Fetch16(0));
281   }
VRegA_22b()282   uint8_t VRegA_22b() const {
283     return VRegA_22b(Fetch16(0));
284   }
VRegA_22c()285   uint4_t VRegA_22c() const {
286     return VRegA_22c(Fetch16(0));
287   }
VRegA_22s()288   uint4_t VRegA_22s() const {
289     return VRegA_22s(Fetch16(0));
290   }
VRegA_22t()291   uint4_t VRegA_22t() const {
292     return VRegA_22t(Fetch16(0));
293   }
VRegA_22x()294   uint8_t VRegA_22x() const {
295     return VRegA_22x(Fetch16(0));
296   }
VRegA_23x()297   uint8_t VRegA_23x() const {
298     return VRegA_23x(Fetch16(0));
299   }
300   int32_t VRegA_30t() const;
VRegA_31c()301   uint8_t VRegA_31c() const {
302     return VRegA_31c(Fetch16(0));
303   }
VRegA_31i()304   uint8_t VRegA_31i() const {
305     return VRegA_31i(Fetch16(0));
306   }
VRegA_31t()307   uint8_t VRegA_31t() const {
308     return VRegA_31t(Fetch16(0));
309   }
310   uint16_t VRegA_32x() const;
VRegA_35c()311   uint4_t VRegA_35c() const {
312     return VRegA_35c(Fetch16(0));
313   }
VRegA_3rc()314   uint8_t VRegA_3rc() const {
315     return VRegA_3rc(Fetch16(0));
316   }
VRegA_51l()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 
VRegB_11n()352   int4_t VRegB_11n() const {
353     return VRegB_11n(Fetch16(0));
354   }
VRegB_12x()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;
VRegB_22c()363   uint4_t VRegB_22c() const {
364     return VRegB_22c(Fetch16(0));
365   }
VRegB_22s()366   uint4_t VRegB_22s() const {
367     return VRegB_22s(Fetch16(0));
368   }
VRegB_22t()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;
GetVarArgs(uint32_t args[kMaxVarArgRegs])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.
Opcode(uint16_t inst_data)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.
Opcode()424   Code Opcode() const {
425     return Opcode(Fetch16(0));
426   }
427 
SetOpcode(Code opcode)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 
SetVRegA_10x(uint8_t val)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 
SetVRegB_3rc(uint16_t val)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 
SetVRegB_35c(uint16_t val)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 
SetVRegC_22c(uint16_t val)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.
FormatOf(Code opcode)459   static Format FormatOf(Code opcode) {
460     return kInstructionFormats[opcode];
461   }
462 
463   // Returns the index type of the given opcode.
IndexTypeOf(Code opcode)464   static IndexType IndexTypeOf(Code opcode) {
465     return kInstructionIndexTypes[opcode];
466   }
467 
468   // Returns the flags for the given opcode.
FlagsOf(Code opcode)469   static int FlagsOf(Code opcode) {
470     return kInstructionFlags[opcode];
471   }
472 
473   // Return the verify flags for the given opcode.
VerifyFlagsOf(Code opcode)474   static int VerifyFlagsOf(Code opcode) {
475     return kInstructionVerifyFlags[opcode];
476   }
477 
478   // Returns true if this instruction is a branch.
IsBranch()479   bool IsBranch() const {
480     return (kInstructionFlags[Opcode()] & kBranch) != 0;
481   }
482 
483   // Returns true if this instruction is a unconditional branch.
IsUnconditional()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.
IsQuickened()495   bool IsQuickened() const {
496     return (kInstructionIndexTypes[Opcode()] == kIndexFieldOffset) ||
497         (kInstructionIndexTypes[Opcode()] == kIndexVtableOffset);
498   }
499 
500   // Returns true if this instruction is a switch.
IsSwitch()501   bool IsSwitch() const {
502     return (kInstructionFlags[Opcode()] & kSwitch) != 0;
503   }
504 
505   // Returns true if this instruction can throw.
IsThrow()506   bool IsThrow() const {
507     return (kInstructionFlags[Opcode()] & kThrow) != 0;
508   }
509 
510   // Determine if the instruction is any of 'return' instructions.
IsReturn()511   bool IsReturn() const {
512     return (kInstructionFlags[Opcode()] & kReturn) != 0;
513   }
514 
515   // Determine if this instruction ends execution of its basic block.
IsBasicBlockEnd()516   bool IsBasicBlockEnd() const {
517     return IsBranch() || IsReturn() || Opcode() == THROW;
518   }
519 
520   // Determine if this instruction is an invoke.
IsInvoke()521   bool IsInvoke() const {
522     return (kInstructionFlags[Opcode()] & kInvoke) != 0;
523   }
524 
525   // Determine if this instruction is experimental.
IsExperimental()526   bool IsExperimental() const {
527     return (kInstructionFlags[Opcode()] & kExperimental) != 0;
528   }
529 
GetVerifyTypeArgumentA()530   int GetVerifyTypeArgumentA() const {
531     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
532   }
533 
GetVerifyTypeArgumentB()534   int GetVerifyTypeArgumentB() const {
535     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField |
536         kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType |
537         kVerifyRegBWide));
538   }
539 
GetVerifyTypeArgumentC()540   int GetVerifyTypeArgumentC() const {
541     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
542         kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide | kVerifyRegCString));
543   }
544 
GetVerifyExtraFlags()545   int GetVerifyExtraFlags() const {
546     return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
547         kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | kVerifyVarArgRange |
548         kVerifyVarArgRangeNonZero | kVerifyError));
549   }
550 
GetVerifyIsRuntimeOnly()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.
GetDexPc(const uint16_t * 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 
Fetch16(size_t offset)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 
Fetch32(size_t offset)578   uint32_t Fetch32(size_t offset) const {
579     return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
580   }
581 
InstA()582   uint4_t InstA() const {
583     return InstA(Fetch16(0));
584   }
585 
InstB()586   uint4_t InstB() const {
587     return InstB(Fetch16(0));
588   }
589 
InstAA()590   uint8_t InstAA() const {
591     return InstAA(Fetch16(0));
592   }
593 
InstA(uint16_t inst_data)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 
InstB(uint16_t inst_data)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 
InstAA(uint16_t inst_data)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