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