blob: 9a1757601c274fa692c28c3c1a435fdbbfaf2321 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Carl Shapiro12eb78e2011-06-24 14:51:06 -070016
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_DEX_INSTRUCTION_H_
18#define ART_RUNTIME_DEX_INSTRUCTION_H_
Carl Shapiro12eb78e2011-06-24 14:51:06 -070019
Elliott Hughes07ed66b2012-12-12 18:34:25 -080020#include "base/logging.h"
Elliott Hughes76160052012-12-12 16:31:20 -080021#include "base/macros.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070022#include "globals.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070023
Sebastien Hertz807a2562013-04-15 09:33:39 +020024typedef uint8_t uint4_t;
25typedef int8_t int4_t;
26
Carl Shapiro12eb78e2011-06-24 14:51:06 -070027namespace art {
28
Ian Rogersd81871c2011-10-03 13:57:23 -070029class DexFile;
30
Elliott Hughesadb8c672012-03-06 16:49:32 -080031enum {
32 kNumPackedOpcodes = 0x100
33};
34
Carl Shapiro12eb78e2011-06-24 14:51:06 -070035class Instruction {
36 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070037 // NOP-encoded switch-statement signatures.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070038 enum Signatures {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070039 kPackedSwitchSignature = 0x0100,
40 kSparseSwitchSignature = 0x0200,
Elliott Hughesadb8c672012-03-06 16:49:32 -080041 kArrayDataSignature = 0x0300,
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070042 };
43
Ian Rogersdf1ce912012-11-27 17:07:11 -080044 struct PACKED(4) PackedSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080045 const uint16_t ident;
46 const uint16_t case_count;
47 const int32_t first_key;
48 const int32_t targets[];
Dragos Sbirlea39f99272013-06-25 13:17:36 -070049
Logan Chien19c350a2012-05-01 19:21:32 +080050 private:
51 DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
52 };
53
Ian Rogersdf1ce912012-11-27 17:07:11 -080054 struct PACKED(4) SparseSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080055 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
Ian Rogersdf1ce912012-11-27 17:07:11 -080072 struct PACKED(4) ArrayDataPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080073 const uint16_t ident;
74 const uint16_t element_width;
75 const uint32_t element_count;
76 const uint8_t data[];
Dragos Sbirlea39f99272013-06-25 13:17:36 -070077
Logan Chien19c350a2012-05-01 19:21:32 +080078 private:
79 DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
80 };
81
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070082 enum Code { // private marker to avoid generate-operator-out.py from processing.
Andreas Gampeae08cc22017-05-15 10:23:02 -070083#define INSTRUCTION_ENUM(opcode, cname, p, f, i, a, e, v) cname = (opcode),
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070084#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070085 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070086#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070087#undef INSTRUCTION_ENUM
Ian Rogersf72a11d2014-10-30 15:41:08 -070088 RSUB_INT_LIT16 = RSUB_INT,
Brian Carlstrom02c8cc62013-07-18 15:54:44 -070089 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070090
Andreas Gampeb3937e32017-05-15 15:11:56 -070091 enum Format : uint8_t {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070092 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
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100115
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
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700124 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
125 };
126
Andreas Gampeb3937e32017-05-15 15:11:56 -0700127 enum IndexType : uint8_t {
Aart Bikb1f37532015-06-29 11:03:55 -0700128 kIndexUnknown = 0,
Orion Hodsonc069a302017-01-18 09:23:12 +0000129 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
Aart Bikb1f37532015-06-29 11:03:55 -0700138 };
139
Andreas Gampeb3937e32017-05-15 15:11:56 -0700140 enum Flags : uint8_t {
Andreas Gampeae08cc22017-05-15 10:23:02 -0700141 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 {
Igor Murashkin158f35c2015-06-10 15:55:30 -0700153 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)
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700170 };
171
Andreas Gampeb3937e32017-05-15 15:11:56 -0700172 enum VerifyFlag : uint32_t {
Orion Hodsonc069a302017-01-18 09:23:12 +0000173 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
jeffhaoba5ebb92011-08-25 17:24:37 -0700199 };
200
Andreas Gampeb3937e32017-05-15 15:11:56 -0700201 // 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
Ian Rogers29a26482014-05-02 15:27:29 -0700210 static constexpr uint32_t kMaxVarArgRegs = 5;
jeffhaoba5ebb92011-08-25 17:24:37 -0700211
Andreas Gampee05cc662017-05-15 10:17:30 -0700212 static constexpr bool kHaveExperimentalInstructions = false;
213
Elliott Hughesadb8c672012-03-06 16:49:32 -0800214 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700215 size_t SizeInCodeUnits() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700216 int8_t result = kInstructionDescriptors[Opcode()].size_in_code_units;
Ian Rogersa75a0132012-09-28 11:41:42 -0700217 if (UNLIKELY(result < 0)) {
218 return SizeInCodeUnitsComplexOpcode();
219 } else {
220 return static_cast<size_t>(result);
221 }
222 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700223
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200224 // Reads an instruction out of the stream at the specified address.
225 static const Instruction* At(const uint16_t* code) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700226 DCHECK(code != nullptr);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200227 return reinterpret_cast<const Instruction*>(code);
228 }
229
230 // Reads an instruction out of the stream from the current address plus an offset.
Ian Rogers7b078e82014-09-10 14:44:24 -0700231 const Instruction* RelativeAt(int32_t offset) const WARN_UNUSED {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200232 return At(reinterpret_cast<const uint16_t*>(this) + offset);
233 }
234
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700235 // Returns a pointer to the next instruction in the stream.
Ian Rogersa75a0132012-09-28 11:41:42 -0700236 const Instruction* Next() const {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200237 return RelativeAt(SizeInCodeUnits());
Ian Rogersa75a0132012-09-28 11:41:42 -0700238 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700239
Jeff Hao9cec2472013-05-14 18:17:06 -0700240 // Returns a pointer to the instruction after this 1xx instruction in the stream.
241 const Instruction* Next_1xx() const {
242 DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200243 return RelativeAt(1);
Jeff Hao9cec2472013-05-14 18:17:06 -0700244 }
245
246 // Returns a pointer to the instruction after this 2xx instruction in the stream.
247 const Instruction* Next_2xx() const {
Narayan Kamath14832ef2016-08-05 11:44:32 +0100248 DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200249 return RelativeAt(2);
Jeff Hao9cec2472013-05-14 18:17:06 -0700250 }
251
252 // Returns a pointer to the instruction after this 3xx instruction in the stream.
253 const Instruction* Next_3xx() const {
254 DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200255 return RelativeAt(3);
Jeff Hao9cec2472013-05-14 18:17:06 -0700256 }
257
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100258 // Returns a pointer to the instruction after this 4xx instruction in the stream.
259 const Instruction* Next_4xx() const {
260 DCHECK(FormatOf(Opcode()) >= k45cc && FormatOf(Opcode()) <= k4rcc);
261 return RelativeAt(4);
262 }
263
Jeff Hao9cec2472013-05-14 18:17:06 -0700264 // Returns a pointer to the instruction after this 51l instruction in the stream.
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200265 const Instruction* Next_51l() const {
266 DCHECK(FormatOf(Opcode()) == k51l);
267 return RelativeAt(5);
268 }
Jeff Hao9cec2472013-05-14 18:17:06 -0700269
Elliott Hughesadb8c672012-03-06 16:49:32 -0800270 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700271 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800272 return Instruction::Name(Opcode());
273 }
274
275 // Returns the name of the given opcode.
276 static const char* Name(Code opcode) {
277 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700278 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700279
Sebastien Hertz807a2562013-04-15 09:33:39 +0200280 // VRegA
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700281 bool HasVRegA() const;
Mathieu Chartierde40d472015-10-15 17:47:48 -0700282 ALWAYS_INLINE int32_t VRegA() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200283
284 int8_t VRegA_10t() const {
285 return VRegA_10t(Fetch16(0));
286 }
287 uint8_t VRegA_10x() const {
288 return VRegA_10x(Fetch16(0));
289 }
290 uint4_t VRegA_11n() const {
291 return VRegA_11n(Fetch16(0));
292 }
293 uint8_t VRegA_11x() const {
294 return VRegA_11x(Fetch16(0));
295 }
296 uint4_t VRegA_12x() const {
297 return VRegA_12x(Fetch16(0));
298 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200299 int16_t VRegA_20t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200300 uint8_t VRegA_21c() const {
301 return VRegA_21c(Fetch16(0));
302 }
303 uint8_t VRegA_21h() const {
304 return VRegA_21h(Fetch16(0));
305 }
306 uint8_t VRegA_21s() const {
307 return VRegA_21s(Fetch16(0));
308 }
309 uint8_t VRegA_21t() const {
310 return VRegA_21t(Fetch16(0));
311 }
312 uint8_t VRegA_22b() const {
313 return VRegA_22b(Fetch16(0));
314 }
315 uint4_t VRegA_22c() const {
316 return VRegA_22c(Fetch16(0));
317 }
318 uint4_t VRegA_22s() const {
319 return VRegA_22s(Fetch16(0));
320 }
321 uint4_t VRegA_22t() const {
322 return VRegA_22t(Fetch16(0));
323 }
324 uint8_t VRegA_22x() const {
325 return VRegA_22x(Fetch16(0));
326 }
327 uint8_t VRegA_23x() const {
328 return VRegA_23x(Fetch16(0));
329 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200330 int32_t VRegA_30t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200331 uint8_t VRegA_31c() const {
332 return VRegA_31c(Fetch16(0));
333 }
334 uint8_t VRegA_31i() const {
335 return VRegA_31i(Fetch16(0));
336 }
337 uint8_t VRegA_31t() const {
338 return VRegA_31t(Fetch16(0));
339 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200340 uint16_t VRegA_32x() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200341 uint4_t VRegA_35c() const {
342 return VRegA_35c(Fetch16(0));
343 }
344 uint8_t VRegA_3rc() const {
345 return VRegA_3rc(Fetch16(0));
346 }
347 uint8_t VRegA_51l() const {
348 return VRegA_51l(Fetch16(0));
349 }
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100350 uint4_t VRegA_45cc() const {
351 return VRegA_45cc(Fetch16(0));
352 }
353 uint8_t VRegA_4rcc() const {
354 return VRegA_4rcc(Fetch16(0));
355 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200356
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;
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100380 uint4_t VRegA_45cc(uint16_t inst_data) const;
381 uint8_t VRegA_4rcc(uint16_t inst_data) const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200382
383 // VRegB
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700384 bool HasVRegB() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700385 int32_t VRegB() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200386
Ian Rogers29a26482014-05-02 15:27:29 -0700387 bool HasWideVRegB() const;
388 uint64_t WideVRegB() const;
389
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200390 int4_t VRegB_11n() const {
391 return VRegB_11n(Fetch16(0));
392 }
393 uint4_t VRegB_12x() const {
394 return VRegB_12x(Fetch16(0));
395 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200396 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;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200401 uint4_t VRegB_22c() const {
402 return VRegB_22c(Fetch16(0));
403 }
404 uint4_t VRegB_22s() const {
405 return VRegB_22s(Fetch16(0));
406 }
407 uint4_t VRegB_22t() const {
408 return VRegB_22t(Fetch16(0));
409 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200410 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;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700418 uint64_t VRegB_51l() const; // vB_wide
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100419 uint16_t VRegB_45cc() const;
420 uint16_t VRegB_4rcc() const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200421
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200422 // 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
Sebastien Hertz807a2562013-04-15 09:33:39 +0200431 // VRegC
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700432 bool HasVRegC() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700433 int32_t VRegC() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200434
Sebastien Hertz807a2562013-04-15 09:33:39 +0200435 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;
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100442 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;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200451
452 // Fills the given array with the 'arg' array of the instruction.
Narayan Kamath14832ef2016-08-05 11:44:32 +0100453 bool HasVarArgs() const;
Ian Rogers29a26482014-05-02 15:27:29 -0700454 void GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
455 void GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
456 return GetVarArgs(args, Fetch16(0));
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200457 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200458
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200459 // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
460 // 16 bits of instruction.
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.
Ian Rogersa75a0132012-09-28 11:41:42 -0700467 Code Opcode() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200468 return Opcode(Fetch16(0));
Ian Rogersa75a0132012-09-28 11:41:42 -0700469 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700470
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200471 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
Sebastien Hertz543959c2013-07-03 12:00:19 +0200477 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
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200483 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
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
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
Nicolas Geoffray01b70e82016-11-17 10:58:36 +0000501 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
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
Elliott Hughesadb8c672012-03-06 16:49:32 -0800513 // Returns the format of the given opcode.
514 static Format FormatOf(Code opcode) {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700515 return kInstructionDescriptors[opcode].format;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700516 }
517
Aart Bikb1f37532015-06-29 11:03:55 -0700518 // Returns the index type of the given opcode.
519 static IndexType IndexTypeOf(Code opcode) {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700520 return kInstructionDescriptors[opcode].index_type;
Aart Bikb1f37532015-06-29 11:03:55 -0700521 }
522
Elliott Hughesadb8c672012-03-06 16:49:32 -0800523 // Returns the flags for the given opcode.
Andreas Gampeb3937e32017-05-15 15:11:56 -0700524 static uint8_t FlagsOf(Code opcode) {
525 return kInstructionDescriptors[opcode].flags;
jeffhaobdb76512011-09-07 11:43:16 -0700526 }
527
buzbeeb1f1d642014-02-27 12:55:32 -0800528 // Return the verify flags for the given opcode.
Andreas Gampeb3937e32017-05-15 15:11:56 -0700529 static uint32_t VerifyFlagsOf(Code opcode) {
530 return kInstructionDescriptors[opcode].verify_flags;
buzbeeb1f1d642014-02-27 12:55:32 -0800531 }
532
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700533 // Returns true if this instruction is a branch.
534 bool IsBranch() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700535 return (kInstructionDescriptors[Opcode()].flags & kBranch) != 0;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700536 }
537
TDYa127526643e2012-05-26 01:01:48 -0700538 // Returns true if this instruction is a unconditional branch.
539 bool IsUnconditional() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700540 return (kInstructionDescriptors[Opcode()].flags & kUnconditional) != 0;
TDYa127526643e2012-05-26 01:01:48 -0700541 }
542
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700543 // 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
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +0000549 // Returns true if the instruction is a quickened instruction.
550 bool IsQuickened() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700551 return (kInstructionDescriptors[Opcode()].index_type == kIndexFieldOffset) ||
552 (kInstructionDescriptors[Opcode()].index_type == kIndexVtableOffset);
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +0000553 }
554
jeffhaoba5ebb92011-08-25 17:24:37 -0700555 // Returns true if this instruction is a switch.
556 bool IsSwitch() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700557 return (kInstructionDescriptors[Opcode()].flags & kSwitch) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700558 }
559
560 // Returns true if this instruction can throw.
561 bool IsThrow() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700562 return (kInstructionDescriptors[Opcode()].flags & kThrow) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700563 }
564
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700565 // Determine if the instruction is any of 'return' instructions.
566 bool IsReturn() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700567 return (kInstructionDescriptors[Opcode()].flags & kReturn) != 0;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700568 }
569
570 // Determine if this instruction ends execution of its basic block.
571 bool IsBasicBlockEnd() const {
572 return IsBranch() || IsReturn() || Opcode() == THROW;
573 }
574
575 // Determine if this instruction is an invoke.
576 bool IsInvoke() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700577 return (kInstructionDescriptors[Opcode()].flags & kInvoke) != 0;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700578 }
579
Igor Murashkin158f35c2015-06-10 15:55:30 -0700580 // Determine if this instruction is experimental.
581 bool IsExperimental() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700582 return (kInstructionDescriptors[Opcode()].flags & kExperimental) != 0;
Igor Murashkin158f35c2015-06-10 15:55:30 -0700583 }
584
jeffhaoba5ebb92011-08-25 17:24:37 -0700585 int GetVerifyTypeArgumentA() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700586 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegA | kVerifyRegAWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700587 }
588
589 int GetVerifyTypeArgumentB() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700590 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegB | kVerifyRegBField |
Ian Rogers5fb22a92014-06-13 10:31:28 -0700591 kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType |
592 kVerifyRegBWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700593 }
594
595 int GetVerifyTypeArgumentC() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700596 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegC | kVerifyRegCField |
Narayan Kamath14832ef2016-08-05 11:44:32 +0100597 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700598 }
599
Orion Hodsoncfa325e2016-10-13 10:25:54 +0100600 int GetVerifyTypeArgumentH() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700601 return (kInstructionDescriptors[Opcode()].verify_flags & kVerifyRegHPrototype);
Orion Hodsoncfa325e2016-10-13 10:25:54 +0100602 }
603
jeffhaoba5ebb92011-08-25 17:24:37 -0700604 int GetVerifyExtraFlags() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700605 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyArrayData |
606 kVerifyBranchTarget | kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero |
607 kVerifyVarArgRange | kVerifyVarArgRangeNonZero | kVerifyError));
Ian Rogers5fb22a92014-06-13 10:31:28 -0700608 }
609
610 bool GetVerifyIsRuntimeOnly() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700611 return (kInstructionDescriptors[Opcode()].verify_flags & kVerifyRuntimeOnly) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700612 }
613
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700614 // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
615 uint32_t GetDexPc(const uint16_t* insns) const {
616 return (reinterpret_cast<const uint16_t*>(this) - insns);
617 }
618
Ian Rogersd81871c2011-10-03 13:57:23 -0700619 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700620 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;
Ian Rogersd81871c2011-10-03 13:57:23 -0700624
Anestis Bechtsoudis32f500d2015-02-22 22:32:57 -0800625 // 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
Sebastien Hertz807a2562013-04-15 09:33:39 +0200629 uint16_t Fetch16(size_t offset) const {
630 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
631 return insns[offset];
632 }
633
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200634 private:
635 size_t SizeInCodeUnitsComplexOpcode() const;
636
Sebastien Hertz807a2562013-04-15 09:33:39 +0200637 uint32_t Fetch32(size_t offset) const {
638 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
639 }
640
641 uint4_t InstA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200642 return InstA(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200643 }
644
645 uint4_t InstB() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200646 return InstB(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200647 }
648
649 uint8_t InstAA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200650 return InstAA(Fetch16(0));
651 }
652
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
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
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);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200666 }
667
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700668 static const char* const kInstructionNames[];
Andreas Gampeb3937e32017-05-15 15:11:56 -0700669
670 static const InstructionDescriptor kInstructionDescriptors[];
671
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700672 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
673};
Ian Rogersa75a0132012-09-28 11:41:42 -0700674std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
675std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
676std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
677std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800678
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700679} // namespace art
680
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700681#endif // ART_RUNTIME_DEX_INSTRUCTION_H_