blob: 7e43f75786ad9d7de0bae3b78fd43b34ac9830fa [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
David Sehr334b9d72018-02-12 18:27:56 -080017#ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
18#define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
Carl Shapiro12eb78e2011-06-24 14:51:06 -070019
Andreas Gampe57943812017-12-06 21:39:13 -080020#include <android-base/logging.h>
21
David Sehr67bf42e2018-02-26 16:43:04 -080022#include "base/globals.h"
Elliott Hughes76160052012-12-12 16:31:20 -080023#include "base/macros.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070024
Sebastien Hertz807a2562013-04-15 09:33:39 +020025typedef uint8_t uint4_t;
26typedef int8_t int4_t;
27
Carl Shapiro12eb78e2011-06-24 14:51:06 -070028namespace art {
29
Ian Rogersd81871c2011-10-03 13:57:23 -070030class DexFile;
31
Elliott Hughesadb8c672012-03-06 16:49:32 -080032enum {
33 kNumPackedOpcodes = 0x100
34};
35
Carl Shapiro12eb78e2011-06-24 14:51:06 -070036class Instruction {
37 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070038 // NOP-encoded switch-statement signatures.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070039 enum Signatures {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070040 kPackedSwitchSignature = 0x0100,
41 kSparseSwitchSignature = 0x0200,
Elliott Hughesadb8c672012-03-06 16:49:32 -080042 kArrayDataSignature = 0x0300,
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070043 };
44
Ian Rogersdf1ce912012-11-27 17:07:11 -080045 struct PACKED(4) PackedSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080046 const uint16_t ident;
47 const uint16_t case_count;
48 const int32_t first_key;
49 const int32_t targets[];
Dragos Sbirlea39f99272013-06-25 13:17:36 -070050
Logan Chien19c350a2012-05-01 19:21:32 +080051 private:
52 DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
53 };
54
Ian Rogersdf1ce912012-11-27 17:07:11 -080055 struct PACKED(4) SparseSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080056 const uint16_t ident;
57 const uint16_t case_count;
58 const int32_t keys_and_targets[];
59
60 public:
61 const int32_t* GetKeys() const {
62 return keys_and_targets;
63 }
64
65 const int32_t* GetTargets() const {
66 return keys_and_targets + case_count;
67 }
68
69 private:
70 DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
71 };
72
Ian Rogersdf1ce912012-11-27 17:07:11 -080073 struct PACKED(4) ArrayDataPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080074 const uint16_t ident;
75 const uint16_t element_width;
76 const uint32_t element_count;
77 const uint8_t data[];
Dragos Sbirlea39f99272013-06-25 13:17:36 -070078
Logan Chien19c350a2012-05-01 19:21:32 +080079 private:
80 DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
81 };
82
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070083 enum Code { // private marker to avoid generate-operator-out.py from processing.
Andreas Gampeae08cc22017-05-15 10:23:02 -070084#define INSTRUCTION_ENUM(opcode, cname, p, f, i, a, e, v) cname = (opcode),
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070085#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070086 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070087#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070088#undef INSTRUCTION_ENUM
Ian Rogersf72a11d2014-10-30 15:41:08 -070089 RSUB_INT_LIT16 = RSUB_INT,
Brian Carlstrom02c8cc62013-07-18 15:54:44 -070090 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070091
Andreas Gampeb3937e32017-05-15 15:11:56 -070092 enum Format : uint8_t {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070093 k10x, // op
94 k12x, // op vA, vB
95 k11n, // op vA, #+B
96 k11x, // op vAA
97 k10t, // op +AA
98 k20t, // op +AAAA
99 k22x, // op vAA, vBBBB
100 k21t, // op vAA, +BBBB
101 k21s, // op vAA, #+BBBB
102 k21h, // op vAA, #+BBBB00000[00000000]
103 k21c, // op vAA, thing@BBBB
104 k23x, // op vAA, vBB, vCC
105 k22b, // op vAA, vBB, #+CC
106 k22t, // op vA, vB, +CCCC
107 k22s, // op vA, vB, #+CCCC
108 k22c, // op vA, vB, thing@CCCC
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
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100116
117 // op {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH (A: count)
118 // format: AG op BBBB FEDC HHHH
119 k45cc,
120
121 // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH (AA: count)
122 // format: AA op BBBB CCCC HHHH
123 k4rcc, // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH (AA: count)
124
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700125 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
David Srbecky436f6c12019-05-22 13:28:42 +0100126 kInvalidFormat,
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700127 };
128
Andreas Gampeb3937e32017-05-15 15:11:56 -0700129 enum IndexType : uint8_t {
Aart Bikb1f37532015-06-29 11:03:55 -0700130 kIndexUnknown = 0,
Orion Hodsonc069a302017-01-18 09:23:12 +0000131 kIndexNone, // has no index
132 kIndexTypeRef, // type reference index
133 kIndexStringRef, // string reference index
134 kIndexMethodRef, // method reference index
135 kIndexFieldRef, // field reference index
136 kIndexFieldOffset, // field offset (for static linked fields)
137 kIndexVtableOffset, // vtable offset (for static linked methods)
138 kIndexMethodAndProtoRef, // method and a proto reference index (for invoke-polymorphic)
139 kIndexCallSiteRef, // call site reference index
Orion Hodson2e599942017-09-22 16:17:41 +0100140 kIndexMethodHandleRef, // constant method handle reference index
141 kIndexProtoRef, // prototype reference index
Aart Bikb1f37532015-06-29 11:03:55 -0700142 };
143
Vladimir Marko9974e3c2020-06-10 16:27:06 +0100144 enum Flags : uint8_t { // private marker to avoid generate-operator-out.py from processing.
Andreas Gampeae08cc22017-05-15 10:23:02 -0700145 kBranch = 0x01, // conditional or unconditional branch
146 kContinue = 0x02, // flow can continue to next statement
147 kSwitch = 0x04, // switch statement
148 kThrow = 0x08, // could cause an exception to be thrown
149 kReturn = 0x10, // returns, no additional statements
150 kInvoke = 0x20, // a flavor of invoke
151 kUnconditional = 0x40, // unconditional branch
152 kExperimental = 0x80, // is an experimental opcode
153 };
154
155 // Old flags. Keeping them around in case we might need them again some day.
156 enum ExtendedFlags : uint32_t {
Igor Murashkin158f35c2015-06-10 15:55:30 -0700157 kAdd = 0x0000080, // addition
158 kSubtract = 0x0000100, // subtract
159 kMultiply = 0x0000200, // multiply
160 kDivide = 0x0000400, // division
161 kRemainder = 0x0000800, // remainder
162 kAnd = 0x0001000, // and
163 kOr = 0x0002000, // or
164 kXor = 0x0004000, // xor
165 kShl = 0x0008000, // shl
166 kShr = 0x0010000, // shr
167 kUshr = 0x0020000, // ushr
168 kCast = 0x0040000, // cast
169 kStore = 0x0080000, // store opcode
170 kLoad = 0x0100000, // load opcode
171 kClobber = 0x0200000, // clobbers memory in a big way (not just a write)
172 kRegCFieldOrConstant = 0x0400000, // is the third virtual register a field or literal constant (vC)
173 kRegBFieldOrConstant = 0x0800000, // is the second virtual register a field or literal constant (vB)
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700174 };
175
Vladimir Marko9974e3c2020-06-10 16:27:06 +0100176 enum VerifyFlag : uint32_t { // private marker to avoid generate-operator-out.py from processing.
Orion Hodsonec3adef2018-11-14 16:16:37 +0000177 kVerifyNothing = 0x0000000,
Orion Hodsonc069a302017-01-18 09:23:12 +0000178 kVerifyRegA = 0x0000001,
179 kVerifyRegAWide = 0x0000002,
180 kVerifyRegB = 0x0000004,
181 kVerifyRegBField = 0x0000008,
182 kVerifyRegBMethod = 0x0000010,
183 kVerifyRegBNewInstance = 0x0000020,
184 kVerifyRegBString = 0x0000040,
185 kVerifyRegBType = 0x0000080,
186 kVerifyRegBWide = 0x0000100,
187 kVerifyRegC = 0x0000200,
188 kVerifyRegCField = 0x0000400,
189 kVerifyRegCNewArray = 0x0000800,
190 kVerifyRegCType = 0x0001000,
191 kVerifyRegCWide = 0x0002000,
192 kVerifyArrayData = 0x0004000,
193 kVerifyBranchTarget = 0x0008000,
194 kVerifySwitchTargets = 0x0010000,
195 kVerifyVarArg = 0x0020000,
196 kVerifyVarArgNonZero = 0x0040000,
197 kVerifyVarArgRange = 0x0080000,
198 kVerifyVarArgRangeNonZero = 0x0100000,
199 kVerifyRuntimeOnly = 0x0200000,
200 kVerifyError = 0x0400000,
201 kVerifyRegHPrototype = 0x0800000,
Orion Hodson2e599942017-09-22 16:17:41 +0100202 kVerifyRegBCallSite = 0x1000000,
203 kVerifyRegBMethodHandle = 0x2000000,
204 kVerifyRegBPrototype = 0x4000000,
jeffhaoba5ebb92011-08-25 17:24:37 -0700205 };
206
Andreas Gampeb3937e32017-05-15 15:11:56 -0700207 // Collect the enums in a struct for better locality.
208 struct InstructionDescriptor {
209 uint32_t verify_flags; // Set of VerifyFlag.
210 Format format;
211 IndexType index_type;
212 uint8_t flags; // Set of Flags.
213 int8_t size_in_code_units;
214 };
215
Ian Rogers29a26482014-05-02 15:27:29 -0700216 static constexpr uint32_t kMaxVarArgRegs = 5;
jeffhaoba5ebb92011-08-25 17:24:37 -0700217
Andreas Gampee05cc662017-05-15 10:17:30 -0700218 static constexpr bool kHaveExperimentalInstructions = false;
219
Elliott Hughesadb8c672012-03-06 16:49:32 -0800220 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700221 size_t SizeInCodeUnits() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700222 int8_t result = kInstructionDescriptors[Opcode()].size_in_code_units;
Ian Rogersa75a0132012-09-28 11:41:42 -0700223 if (UNLIKELY(result < 0)) {
224 return SizeInCodeUnitsComplexOpcode();
225 } else {
226 return static_cast<size_t>(result);
227 }
228 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700229
David Srbecky8867f3b2019-05-31 20:01:46 +0100230 // Returns the size (in 2 byte code units) of the given instruction format.
231 ALWAYS_INLINE static constexpr size_t SizeInCodeUnits(Format format);
232
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700233 // Code units required to calculate the size of the instruction.
234 size_t CodeUnitsRequiredForSizeComputation() const {
235 const int8_t result = kInstructionDescriptors[Opcode()].size_in_code_units;
236 return UNLIKELY(result < 0) ? CodeUnitsRequiredForSizeOfComplexOpcode() : 1;
237 }
238
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200239 // Reads an instruction out of the stream at the specified address.
240 static const Instruction* At(const uint16_t* code) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700241 DCHECK(code != nullptr);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200242 return reinterpret_cast<const Instruction*>(code);
243 }
244
245 // Reads an instruction out of the stream from the current address plus an offset.
Ian Rogers7b078e82014-09-10 14:44:24 -0700246 const Instruction* RelativeAt(int32_t offset) const WARN_UNUSED {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200247 return At(reinterpret_cast<const uint16_t*>(this) + offset);
248 }
249
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700250 // Returns a pointer to the next instruction in the stream.
Ian Rogersa75a0132012-09-28 11:41:42 -0700251 const Instruction* Next() const {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200252 return RelativeAt(SizeInCodeUnits());
Ian Rogersa75a0132012-09-28 11:41:42 -0700253 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700254
Jeff Hao9cec2472013-05-14 18:17:06 -0700255 // Returns a pointer to the instruction after this 1xx instruction in the stream.
256 const Instruction* Next_1xx() const {
257 DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200258 return RelativeAt(1);
Jeff Hao9cec2472013-05-14 18:17:06 -0700259 }
260
261 // Returns a pointer to the instruction after this 2xx instruction in the stream.
262 const Instruction* Next_2xx() const {
Narayan Kamath14832ef2016-08-05 11:44:32 +0100263 DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200264 return RelativeAt(2);
Jeff Hao9cec2472013-05-14 18:17:06 -0700265 }
266
267 // Returns a pointer to the instruction after this 3xx instruction in the stream.
268 const Instruction* Next_3xx() const {
269 DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200270 return RelativeAt(3);
Jeff Hao9cec2472013-05-14 18:17:06 -0700271 }
272
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100273 // Returns a pointer to the instruction after this 4xx instruction in the stream.
274 const Instruction* Next_4xx() const {
275 DCHECK(FormatOf(Opcode()) >= k45cc && FormatOf(Opcode()) <= k4rcc);
276 return RelativeAt(4);
277 }
278
Jeff Hao9cec2472013-05-14 18:17:06 -0700279 // Returns a pointer to the instruction after this 51l instruction in the stream.
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200280 const Instruction* Next_51l() const {
281 DCHECK(FormatOf(Opcode()) == k51l);
282 return RelativeAt(5);
283 }
Jeff Hao9cec2472013-05-14 18:17:06 -0700284
Elliott Hughesadb8c672012-03-06 16:49:32 -0800285 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700286 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800287 return Instruction::Name(Opcode());
288 }
289
290 // Returns the name of the given opcode.
291 static const char* Name(Code opcode) {
292 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700293 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700294
Sebastien Hertz807a2562013-04-15 09:33:39 +0200295 // VRegA
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700296 bool HasVRegA() const;
Mathieu Chartierde40d472015-10-15 17:47:48 -0700297 ALWAYS_INLINE int32_t VRegA() const;
David Srbecky436f6c12019-05-22 13:28:42 +0100298 ALWAYS_INLINE int32_t VRegA(Format format, uint16_t inst_data) const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200299
300 int8_t VRegA_10t() const {
301 return VRegA_10t(Fetch16(0));
302 }
303 uint8_t VRegA_10x() const {
304 return VRegA_10x(Fetch16(0));
305 }
306 uint4_t VRegA_11n() const {
307 return VRegA_11n(Fetch16(0));
308 }
309 uint8_t VRegA_11x() const {
310 return VRegA_11x(Fetch16(0));
311 }
312 uint4_t VRegA_12x() const {
313 return VRegA_12x(Fetch16(0));
314 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200315 int16_t VRegA_20t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200316 uint8_t VRegA_21c() const {
317 return VRegA_21c(Fetch16(0));
318 }
319 uint8_t VRegA_21h() const {
320 return VRegA_21h(Fetch16(0));
321 }
322 uint8_t VRegA_21s() const {
323 return VRegA_21s(Fetch16(0));
324 }
325 uint8_t VRegA_21t() const {
326 return VRegA_21t(Fetch16(0));
327 }
328 uint8_t VRegA_22b() const {
329 return VRegA_22b(Fetch16(0));
330 }
331 uint4_t VRegA_22c() const {
332 return VRegA_22c(Fetch16(0));
333 }
334 uint4_t VRegA_22s() const {
335 return VRegA_22s(Fetch16(0));
336 }
337 uint4_t VRegA_22t() const {
338 return VRegA_22t(Fetch16(0));
339 }
340 uint8_t VRegA_22x() const {
341 return VRegA_22x(Fetch16(0));
342 }
343 uint8_t VRegA_23x() const {
344 return VRegA_23x(Fetch16(0));
345 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200346 int32_t VRegA_30t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200347 uint8_t VRegA_31c() const {
348 return VRegA_31c(Fetch16(0));
349 }
350 uint8_t VRegA_31i() const {
351 return VRegA_31i(Fetch16(0));
352 }
353 uint8_t VRegA_31t() const {
354 return VRegA_31t(Fetch16(0));
355 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200356 uint16_t VRegA_32x() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200357 uint4_t VRegA_35c() const {
358 return VRegA_35c(Fetch16(0));
359 }
360 uint8_t VRegA_3rc() const {
361 return VRegA_3rc(Fetch16(0));
362 }
363 uint8_t VRegA_51l() const {
364 return VRegA_51l(Fetch16(0));
365 }
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100366 uint4_t VRegA_45cc() const {
367 return VRegA_45cc(Fetch16(0));
368 }
369 uint8_t VRegA_4rcc() const {
370 return VRegA_4rcc(Fetch16(0));
371 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200372
373 // The following methods return the vA operand for various instruction formats. The "inst_data"
374 // parameter holds the first 16 bits of instruction which the returned value is decoded from.
375 int8_t VRegA_10t(uint16_t inst_data) const;
376 uint8_t VRegA_10x(uint16_t inst_data) const;
377 uint4_t VRegA_11n(uint16_t inst_data) const;
378 uint8_t VRegA_11x(uint16_t inst_data) const;
379 uint4_t VRegA_12x(uint16_t inst_data) const;
380 uint8_t VRegA_21c(uint16_t inst_data) const;
381 uint8_t VRegA_21h(uint16_t inst_data) const;
382 uint8_t VRegA_21s(uint16_t inst_data) const;
383 uint8_t VRegA_21t(uint16_t inst_data) const;
384 uint8_t VRegA_22b(uint16_t inst_data) const;
385 uint4_t VRegA_22c(uint16_t inst_data) const;
386 uint4_t VRegA_22s(uint16_t inst_data) const;
387 uint4_t VRegA_22t(uint16_t inst_data) const;
388 uint8_t VRegA_22x(uint16_t inst_data) const;
389 uint8_t VRegA_23x(uint16_t inst_data) const;
390 uint8_t VRegA_31c(uint16_t inst_data) const;
391 uint8_t VRegA_31i(uint16_t inst_data) const;
392 uint8_t VRegA_31t(uint16_t inst_data) const;
393 uint4_t VRegA_35c(uint16_t inst_data) const;
394 uint8_t VRegA_3rc(uint16_t inst_data) const;
395 uint8_t VRegA_51l(uint16_t inst_data) const;
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100396 uint4_t VRegA_45cc(uint16_t inst_data) const;
397 uint8_t VRegA_4rcc(uint16_t inst_data) const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200398
399 // VRegB
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700400 bool HasVRegB() const;
David Srbecky436f6c12019-05-22 13:28:42 +0100401 ALWAYS_INLINE int32_t VRegB() const;
402 ALWAYS_INLINE int32_t VRegB(Format format, uint16_t inst_data) const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200403
Ian Rogers29a26482014-05-02 15:27:29 -0700404 bool HasWideVRegB() const;
405 uint64_t WideVRegB() const;
406
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200407 int4_t VRegB_11n() const {
408 return VRegB_11n(Fetch16(0));
409 }
410 uint4_t VRegB_12x() const {
411 return VRegB_12x(Fetch16(0));
412 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200413 uint16_t VRegB_21c() const;
414 uint16_t VRegB_21h() const;
415 int16_t VRegB_21s() const;
416 int16_t VRegB_21t() const;
417 uint8_t VRegB_22b() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200418 uint4_t VRegB_22c() const {
419 return VRegB_22c(Fetch16(0));
420 }
421 uint4_t VRegB_22s() const {
422 return VRegB_22s(Fetch16(0));
423 }
424 uint4_t VRegB_22t() const {
425 return VRegB_22t(Fetch16(0));
426 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200427 uint16_t VRegB_22x() const;
428 uint8_t VRegB_23x() const;
429 uint32_t VRegB_31c() const;
430 int32_t VRegB_31i() const;
431 int32_t VRegB_31t() const;
432 uint16_t VRegB_32x() const;
433 uint16_t VRegB_35c() const;
434 uint16_t VRegB_3rc() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700435 uint64_t VRegB_51l() const; // vB_wide
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100436 uint16_t VRegB_45cc() const;
437 uint16_t VRegB_4rcc() const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200438
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200439 // The following methods return the vB operand for all instruction formats where it is encoded in
440 // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
441 // value is decoded from it.
442 int4_t VRegB_11n(uint16_t inst_data) const;
443 uint4_t VRegB_12x(uint16_t inst_data) const;
444 uint4_t VRegB_22c(uint16_t inst_data) const;
445 uint4_t VRegB_22s(uint16_t inst_data) const;
446 uint4_t VRegB_22t(uint16_t inst_data) const;
447
Sebastien Hertz807a2562013-04-15 09:33:39 +0200448 // VRegC
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700449 bool HasVRegC() const;
David Srbecky436f6c12019-05-22 13:28:42 +0100450 ALWAYS_INLINE int32_t VRegC() const;
451 ALWAYS_INLINE int32_t VRegC(Format format) const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200452
Sebastien Hertz807a2562013-04-15 09:33:39 +0200453 int8_t VRegC_22b() const;
454 uint16_t VRegC_22c() const;
455 int16_t VRegC_22s() const;
456 int16_t VRegC_22t() const;
457 uint8_t VRegC_23x() const;
458 uint4_t VRegC_35c() const;
459 uint16_t VRegC_3rc() const;
Narayan Kamath8ec3bd22016-08-03 12:46:23 +0100460 uint4_t VRegC_45cc() const;
461 uint16_t VRegC_4rcc() const;
462
463
464 // VRegH
465 bool HasVRegH() const;
466 int32_t VRegH() const;
467 uint16_t VRegH_45cc() const;
468 uint16_t VRegH_4rcc() const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200469
470 // Fills the given array with the 'arg' array of the instruction.
Narayan Kamath14832ef2016-08-05 11:44:32 +0100471 bool HasVarArgs() const;
Treehugger Robot2c5827a2018-05-17 22:26:08 +0000472 uint32_t GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
473 uint32_t GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
Ian Rogers29a26482014-05-02 15:27:29 -0700474 return GetVarArgs(args, Fetch16(0));
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200475 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200476
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200477 // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
478 // 16 bits of instruction.
479 Code Opcode(uint16_t inst_data) const {
480 DCHECK_EQ(inst_data, Fetch16(0));
481 return static_cast<Code>(inst_data & 0xFF);
482 }
483
484 // Returns the opcode field of the instruction from the first 16 bits of instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700485 Code Opcode() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200486 return Opcode(Fetch16(0));
Ian Rogersa75a0132012-09-28 11:41:42 -0700487 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700488
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200489 void SetOpcode(Code opcode) {
490 DCHECK_LT(static_cast<uint16_t>(opcode), 256u);
491 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
492 insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode);
493 }
494
Sebastien Hertz543959c2013-07-03 12:00:19 +0200495 void SetVRegA_10x(uint8_t val) {
496 DCHECK(FormatOf(Opcode()) == k10x);
497 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
498 insns[0] = (val << 8) | (insns[0] & 0x00ff);
499 }
500
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200501 void SetVRegB_3rc(uint16_t val) {
502 DCHECK(FormatOf(Opcode()) == k3rc);
503 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
504 insns[1] = val;
505 }
506
507 void SetVRegB_35c(uint16_t val) {
508 DCHECK(FormatOf(Opcode()) == k35c);
509 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
510 insns[1] = val;
511 }
512
513 void SetVRegC_22c(uint16_t val) {
514 DCHECK(FormatOf(Opcode()) == k22c);
515 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
516 insns[1] = val;
517 }
518
Nicolas Geoffray01b70e82016-11-17 10:58:36 +0000519 void SetVRegA_21c(uint8_t val) {
520 DCHECK(FormatOf(Opcode()) == k21c);
521 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
522 insns[0] = (val << 8) | (insns[0] & 0x00ff);
523 }
524
525 void SetVRegB_21c(uint16_t val) {
526 DCHECK(FormatOf(Opcode()) == k21c);
527 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
528 insns[1] = val;
529 }
530
Elliott Hughesadb8c672012-03-06 16:49:32 -0800531 // Returns the format of the given opcode.
532 static Format FormatOf(Code opcode) {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700533 return kInstructionDescriptors[opcode].format;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700534 }
535
Aart Bikb1f37532015-06-29 11:03:55 -0700536 // Returns the index type of the given opcode.
537 static IndexType IndexTypeOf(Code opcode) {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700538 return kInstructionDescriptors[opcode].index_type;
Aart Bikb1f37532015-06-29 11:03:55 -0700539 }
540
Elliott Hughesadb8c672012-03-06 16:49:32 -0800541 // Returns the flags for the given opcode.
Andreas Gampeb3937e32017-05-15 15:11:56 -0700542 static uint8_t FlagsOf(Code opcode) {
543 return kInstructionDescriptors[opcode].flags;
jeffhaobdb76512011-09-07 11:43:16 -0700544 }
545
buzbeeb1f1d642014-02-27 12:55:32 -0800546 // Return the verify flags for the given opcode.
Andreas Gampeb3937e32017-05-15 15:11:56 -0700547 static uint32_t VerifyFlagsOf(Code opcode) {
548 return kInstructionDescriptors[opcode].verify_flags;
buzbeeb1f1d642014-02-27 12:55:32 -0800549 }
550
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700551 // Returns true if this instruction is a branch.
552 bool IsBranch() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700553 return (kInstructionDescriptors[Opcode()].flags & kBranch) != 0;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700554 }
555
TDYa127526643e2012-05-26 01:01:48 -0700556 // Returns true if this instruction is a unconditional branch.
557 bool IsUnconditional() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700558 return (kInstructionDescriptors[Opcode()].flags & kUnconditional) != 0;
TDYa127526643e2012-05-26 01:01:48 -0700559 }
560
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700561 // Returns the branch offset if this instruction is a branch.
562 int32_t GetTargetOffset() const;
563
564 // Returns true if the instruction allows control flow to go to the following instruction.
565 bool CanFlowThrough() const;
566
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +0000567 // Returns true if the instruction is a quickened instruction.
568 bool IsQuickened() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700569 return (kInstructionDescriptors[Opcode()].index_type == kIndexFieldOffset) ||
570 (kInstructionDescriptors[Opcode()].index_type == kIndexVtableOffset);
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +0000571 }
572
jeffhaoba5ebb92011-08-25 17:24:37 -0700573 // Returns true if this instruction is a switch.
574 bool IsSwitch() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700575 return (kInstructionDescriptors[Opcode()].flags & kSwitch) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700576 }
577
578 // Returns true if this instruction can throw.
579 bool IsThrow() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700580 return (kInstructionDescriptors[Opcode()].flags & kThrow) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700581 }
582
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700583 // Determine if the instruction is any of 'return' instructions.
584 bool IsReturn() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700585 return (kInstructionDescriptors[Opcode()].flags & kReturn) != 0;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700586 }
587
588 // Determine if this instruction ends execution of its basic block.
589 bool IsBasicBlockEnd() const {
590 return IsBranch() || IsReturn() || Opcode() == THROW;
591 }
592
593 // Determine if this instruction is an invoke.
594 bool IsInvoke() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700595 return (kInstructionDescriptors[Opcode()].flags & kInvoke) != 0;
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700596 }
597
Igor Murashkin158f35c2015-06-10 15:55:30 -0700598 // Determine if this instruction is experimental.
599 bool IsExperimental() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700600 return (kInstructionDescriptors[Opcode()].flags & kExperimental) != 0;
Igor Murashkin158f35c2015-06-10 15:55:30 -0700601 }
602
jeffhaoba5ebb92011-08-25 17:24:37 -0700603 int GetVerifyTypeArgumentA() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700604 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegA | kVerifyRegAWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700605 }
606
607 int GetVerifyTypeArgumentB() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700608 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegB | kVerifyRegBField |
Ian Rogers5fb22a92014-06-13 10:31:28 -0700609 kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType |
610 kVerifyRegBWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700611 }
612
613 int GetVerifyTypeArgumentC() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700614 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegC | kVerifyRegCField |
Narayan Kamath14832ef2016-08-05 11:44:32 +0100615 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700616 }
617
Orion Hodsoncfa325e2016-10-13 10:25:54 +0100618 int GetVerifyTypeArgumentH() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700619 return (kInstructionDescriptors[Opcode()].verify_flags & kVerifyRegHPrototype);
Orion Hodsoncfa325e2016-10-13 10:25:54 +0100620 }
621
jeffhaoba5ebb92011-08-25 17:24:37 -0700622 int GetVerifyExtraFlags() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700623 return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyArrayData |
624 kVerifyBranchTarget | kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero |
625 kVerifyVarArgRange | kVerifyVarArgRangeNonZero | kVerifyError));
Ian Rogers5fb22a92014-06-13 10:31:28 -0700626 }
627
628 bool GetVerifyIsRuntimeOnly() const {
Andreas Gampeb3937e32017-05-15 15:11:56 -0700629 return (kInstructionDescriptors[Opcode()].verify_flags & kVerifyRuntimeOnly) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700630 }
631
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700632 // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
633 uint32_t GetDexPc(const uint16_t* insns) const {
634 return (reinterpret_cast<const uint16_t*>(this) - insns);
635 }
636
Ian Rogersd81871c2011-10-03 13:57:23 -0700637 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700638 std::string DumpString(const DexFile*) const;
639
640 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
641 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700642
Anestis Bechtsoudis32f500d2015-02-22 22:32:57 -0800643 // Little-endian dump code_units worth of this instruction, padding to code_units for
644 // shorter instructions
645 std::string DumpHexLE(size_t instr_code_units) const;
646
Sebastien Hertz807a2562013-04-15 09:33:39 +0200647 uint16_t Fetch16(size_t offset) const {
648 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
649 return insns[offset];
650 }
651
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200652 private:
653 size_t SizeInCodeUnitsComplexOpcode() const;
654
Mathieu Chartieraf7c9022017-10-27 09:42:46 -0700655 // Return how many code unit words are required to compute the size of the opcode.
656 size_t CodeUnitsRequiredForSizeOfComplexOpcode() const;
657
Sebastien Hertz807a2562013-04-15 09:33:39 +0200658 uint32_t Fetch32(size_t offset) const {
659 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
660 }
661
662 uint4_t InstA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200663 return InstA(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200664 }
665
666 uint4_t InstB() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200667 return InstB(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200668 }
669
670 uint8_t InstAA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200671 return InstAA(Fetch16(0));
672 }
673
674 uint4_t InstA(uint16_t inst_data) const {
675 DCHECK_EQ(inst_data, Fetch16(0));
676 return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
677 }
678
679 uint4_t InstB(uint16_t inst_data) const {
680 DCHECK_EQ(inst_data, Fetch16(0));
681 return static_cast<uint4_t>(inst_data >> 12);
682 }
683
684 uint8_t InstAA(uint16_t inst_data) const {
685 DCHECK_EQ(inst_data, Fetch16(0));
686 return static_cast<uint8_t>(inst_data >> 8);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200687 }
688
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700689 static const char* const kInstructionNames[];
Andreas Gampeb3937e32017-05-15 15:11:56 -0700690
691 static const InstructionDescriptor kInstructionDescriptors[];
692
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700693 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
694};
Vladimir Marko9974e3c2020-06-10 16:27:06 +0100695std::ostream& operator<<(std::ostream& os, Instruction::Code code);
696std::ostream& operator<<(std::ostream& os, Instruction::Format format);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800697
Orion Hodson960d4f72017-11-10 15:32:38 +0000698// Base class for accessing instruction operands. Unifies operand
699// access for instructions that have range and varargs forms
700// (e.g. invoke-polymoprhic/range and invoke-polymorphic).
701class InstructionOperands {
702 public:
703 explicit InstructionOperands(size_t num_operands) : num_operands_(num_operands) {}
704 virtual ~InstructionOperands() {}
705 virtual uint32_t GetOperand(size_t index) const = 0;
706 size_t GetNumberOfOperands() const { return num_operands_; }
707
708 private:
Orion Hodson928033d2018-02-07 05:30:54 +0000709 const size_t num_operands_;
Orion Hodson960d4f72017-11-10 15:32:38 +0000710
711 DISALLOW_IMPLICIT_CONSTRUCTORS(InstructionOperands);
712};
713
714// Class for accessing operands for instructions with a range format
715// (e.g. 3rc and 4rcc).
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100716class RangeInstructionOperands final : public InstructionOperands {
Orion Hodson960d4f72017-11-10 15:32:38 +0000717 public:
718 RangeInstructionOperands(uint32_t first_operand, size_t num_operands)
719 : InstructionOperands(num_operands), first_operand_(first_operand) {}
720 ~RangeInstructionOperands() {}
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100721 uint32_t GetOperand(size_t operand_index) const override;
Orion Hodson960d4f72017-11-10 15:32:38 +0000722
723 private:
724 const uint32_t first_operand_;
725
726 DISALLOW_IMPLICIT_CONSTRUCTORS(RangeInstructionOperands);
727};
728
729// Class for accessing operands for instructions with a variable
730// number of arguments format (e.g. 35c and 45cc).
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100731class VarArgsInstructionOperands final : public InstructionOperands {
Orion Hodson960d4f72017-11-10 15:32:38 +0000732 public:
733 VarArgsInstructionOperands(const uint32_t (&operands)[Instruction::kMaxVarArgRegs],
734 size_t num_operands)
735 : InstructionOperands(num_operands), operands_(operands) {}
736 ~VarArgsInstructionOperands() {}
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100737 uint32_t GetOperand(size_t operand_index) const override;
Orion Hodson960d4f72017-11-10 15:32:38 +0000738
739 private:
740 const uint32_t (&operands_)[Instruction::kMaxVarArgRegs];
741
742 DISALLOW_IMPLICIT_CONSTRUCTORS(VarArgsInstructionOperands);
743};
744
Orion Hodson928033d2018-02-07 05:30:54 +0000745// Class for accessing operands without the receiver by wrapping an
746// existing InstructionOperands instance.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100747class NoReceiverInstructionOperands final : public InstructionOperands {
Orion Hodson928033d2018-02-07 05:30:54 +0000748 public:
Orion Hodsonb8b93872018-01-30 07:51:10 +0000749 explicit NoReceiverInstructionOperands(const InstructionOperands* const inner)
Orion Hodson928033d2018-02-07 05:30:54 +0000750 : InstructionOperands(inner->GetNumberOfOperands() - 1), inner_(inner) {}
751 ~NoReceiverInstructionOperands() {}
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100752 uint32_t GetOperand(size_t operand_index) const override;
Orion Hodson928033d2018-02-07 05:30:54 +0000753
754 private:
755 const InstructionOperands* const inner_;
756
757 DISALLOW_IMPLICIT_CONSTRUCTORS(NoReceiverInstructionOperands);
758};
759
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700760} // namespace art
761
David Sehr334b9d72018-02-12 18:27:56 -0800762#endif // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_