blob: 89c3db62237e31fc11483d5f7b35500034ed0e1d [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.
Chih-Hung Hsiehfba39972016-05-11 11:26:48 -070083#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, 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
Elliott Hughesadb8c672012-03-06 16:49:32 -080091 enum Format {
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
Igor Murashkin158f35c2015-06-10 15:55:30 -0700108 k25x, // op vC, {vD, vE, vF, vG} (B: count)
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700109 k32x, // op vAAAA, vBBBB
110 k30t, // op +AAAAAAAA
111 k31t, // op vAA, +BBBBBBBB
112 k31i, // op vAA, #+BBBBBBBB
113 k31c, // op vAA, thing@BBBBBBBB
114 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
115 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
116 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
117 };
118
Aart Bikb1f37532015-06-29 11:03:55 -0700119 enum IndexType {
120 kIndexUnknown = 0,
121 kIndexNone, // has no index
122 kIndexTypeRef, // type reference index
123 kIndexStringRef, // string reference index
124 kIndexMethodRef, // method reference index
125 kIndexFieldRef, // field reference index
126 kIndexFieldOffset, // field offset (for static linked fields)
127 kIndexVtableOffset // vtable offset (for static linked methods)
128 };
129
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700130 enum Flags {
Igor Murashkin158f35c2015-06-10 15:55:30 -0700131 kBranch = 0x0000001, // conditional or unconditional branch
132 kContinue = 0x0000002, // flow can continue to next statement
133 kSwitch = 0x0000004, // switch statement
134 kThrow = 0x0000008, // could cause an exception to be thrown
135 kReturn = 0x0000010, // returns, no additional statements
136 kInvoke = 0x0000020, // a flavor of invoke
137 kUnconditional = 0x0000040, // unconditional branch
138 kAdd = 0x0000080, // addition
139 kSubtract = 0x0000100, // subtract
140 kMultiply = 0x0000200, // multiply
141 kDivide = 0x0000400, // division
142 kRemainder = 0x0000800, // remainder
143 kAnd = 0x0001000, // and
144 kOr = 0x0002000, // or
145 kXor = 0x0004000, // xor
146 kShl = 0x0008000, // shl
147 kShr = 0x0010000, // shr
148 kUshr = 0x0020000, // ushr
149 kCast = 0x0040000, // cast
150 kStore = 0x0080000, // store opcode
151 kLoad = 0x0100000, // load opcode
152 kClobber = 0x0200000, // clobbers memory in a big way (not just a write)
153 kRegCFieldOrConstant = 0x0400000, // is the third virtual register a field or literal constant (vC)
154 kRegBFieldOrConstant = 0x0800000, // is the second virtual register a field or literal constant (vB)
155 kExperimental = 0x1000000, // is an experimental opcode
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700156 };
157
jeffhaoba5ebb92011-08-25 17:24:37 -0700158 enum VerifyFlag {
Andreas Gampec3314312014-06-19 18:13:29 -0700159 kVerifyNone = 0x000000,
160 kVerifyRegA = 0x000001,
161 kVerifyRegAWide = 0x000002,
162 kVerifyRegB = 0x000004,
163 kVerifyRegBField = 0x000008,
164 kVerifyRegBMethod = 0x000010,
165 kVerifyRegBNewInstance = 0x000020,
166 kVerifyRegBString = 0x000040,
167 kVerifyRegBType = 0x000080,
168 kVerifyRegBWide = 0x000100,
169 kVerifyRegC = 0x000200,
170 kVerifyRegCField = 0x000400,
171 kVerifyRegCNewArray = 0x000800,
172 kVerifyRegCType = 0x001000,
173 kVerifyRegCWide = 0x002000,
174 kVerifyArrayData = 0x004000,
175 kVerifyBranchTarget = 0x008000,
176 kVerifySwitchTargets = 0x010000,
177 kVerifyVarArg = 0x020000,
178 kVerifyVarArgNonZero = 0x040000,
179 kVerifyVarArgRange = 0x080000,
180 kVerifyVarArgRangeNonZero = 0x100000,
181 kVerifyRuntimeOnly = 0x200000,
182 kVerifyError = 0x400000,
Igor Murashkin6918bf12015-09-27 19:19:06 -0700183 kVerifyRegCString = 0x800000,
jeffhaoba5ebb92011-08-25 17:24:37 -0700184 };
185
Ian Rogers29a26482014-05-02 15:27:29 -0700186 static constexpr uint32_t kMaxVarArgRegs = 5;
Igor Murashkin6918bf12015-09-27 19:19:06 -0700187 static constexpr uint32_t kMaxVarArgRegs25x = 6; // lambdas are 2 registers.
Aart Bika3bb7202015-10-26 17:24:09 -0700188 static constexpr uint32_t kLambdaVirtualRegisterWidth = 2;
jeffhaoba5ebb92011-08-25 17:24:37 -0700189
Elliott Hughesadb8c672012-03-06 16:49:32 -0800190 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700191 size_t SizeInCodeUnits() const {
192 int result = kInstructionSizeInCodeUnits[Opcode()];
193 if (UNLIKELY(result < 0)) {
194 return SizeInCodeUnitsComplexOpcode();
195 } else {
196 return static_cast<size_t>(result);
197 }
198 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700199
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200200 // Reads an instruction out of the stream at the specified address.
201 static const Instruction* At(const uint16_t* code) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700202 DCHECK(code != nullptr);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200203 return reinterpret_cast<const Instruction*>(code);
204 }
205
206 // Reads an instruction out of the stream from the current address plus an offset.
Ian Rogers7b078e82014-09-10 14:44:24 -0700207 const Instruction* RelativeAt(int32_t offset) const WARN_UNUSED {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200208 return At(reinterpret_cast<const uint16_t*>(this) + offset);
209 }
210
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700211 // Returns a pointer to the next instruction in the stream.
Ian Rogersa75a0132012-09-28 11:41:42 -0700212 const Instruction* Next() const {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200213 return RelativeAt(SizeInCodeUnits());
Ian Rogersa75a0132012-09-28 11:41:42 -0700214 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700215
Jeff Hao9cec2472013-05-14 18:17:06 -0700216 // Returns a pointer to the instruction after this 1xx instruction in the stream.
217 const Instruction* Next_1xx() const {
218 DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200219 return RelativeAt(1);
Jeff Hao9cec2472013-05-14 18:17:06 -0700220 }
221
222 // Returns a pointer to the instruction after this 2xx instruction in the stream.
223 const Instruction* Next_2xx() const {
Igor Murashkin158f35c2015-06-10 15:55:30 -0700224 DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k25x);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200225 return RelativeAt(2);
Jeff Hao9cec2472013-05-14 18:17:06 -0700226 }
227
228 // Returns a pointer to the instruction after this 3xx instruction in the stream.
229 const Instruction* Next_3xx() const {
230 DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200231 return RelativeAt(3);
Jeff Hao9cec2472013-05-14 18:17:06 -0700232 }
233
234 // Returns a pointer to the instruction after this 51l instruction in the stream.
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200235 const Instruction* Next_51l() const {
236 DCHECK(FormatOf(Opcode()) == k51l);
237 return RelativeAt(5);
238 }
Jeff Hao9cec2472013-05-14 18:17:06 -0700239
Elliott Hughesadb8c672012-03-06 16:49:32 -0800240 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700241 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800242 return Instruction::Name(Opcode());
243 }
244
245 // Returns the name of the given opcode.
246 static const char* Name(Code opcode) {
247 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700248 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700249
Sebastien Hertz807a2562013-04-15 09:33:39 +0200250 // VRegA
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700251 bool HasVRegA() const;
Mathieu Chartierde40d472015-10-15 17:47:48 -0700252 ALWAYS_INLINE int32_t VRegA() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200253
254 int8_t VRegA_10t() const {
255 return VRegA_10t(Fetch16(0));
256 }
257 uint8_t VRegA_10x() const {
258 return VRegA_10x(Fetch16(0));
259 }
260 uint4_t VRegA_11n() const {
261 return VRegA_11n(Fetch16(0));
262 }
263 uint8_t VRegA_11x() const {
264 return VRegA_11x(Fetch16(0));
265 }
266 uint4_t VRegA_12x() const {
267 return VRegA_12x(Fetch16(0));
268 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200269 int16_t VRegA_20t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200270 uint8_t VRegA_21c() const {
271 return VRegA_21c(Fetch16(0));
272 }
273 uint8_t VRegA_21h() const {
274 return VRegA_21h(Fetch16(0));
275 }
276 uint8_t VRegA_21s() const {
277 return VRegA_21s(Fetch16(0));
278 }
279 uint8_t VRegA_21t() const {
280 return VRegA_21t(Fetch16(0));
281 }
282 uint8_t VRegA_22b() const {
283 return VRegA_22b(Fetch16(0));
284 }
285 uint4_t VRegA_22c() const {
286 return VRegA_22c(Fetch16(0));
287 }
288 uint4_t VRegA_22s() const {
289 return VRegA_22s(Fetch16(0));
290 }
291 uint4_t VRegA_22t() const {
292 return VRegA_22t(Fetch16(0));
293 }
294 uint8_t VRegA_22x() const {
295 return VRegA_22x(Fetch16(0));
296 }
297 uint8_t VRegA_23x() const {
298 return VRegA_23x(Fetch16(0));
299 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200300 int32_t VRegA_30t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200301 uint8_t VRegA_31c() const {
302 return VRegA_31c(Fetch16(0));
303 }
304 uint8_t VRegA_31i() const {
305 return VRegA_31i(Fetch16(0));
306 }
307 uint8_t VRegA_31t() const {
308 return VRegA_31t(Fetch16(0));
309 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200310 uint16_t VRegA_32x() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200311 uint4_t VRegA_35c() const {
312 return VRegA_35c(Fetch16(0));
313 }
314 uint8_t VRegA_3rc() const {
315 return VRegA_3rc(Fetch16(0));
316 }
317 uint8_t VRegA_51l() const {
318 return VRegA_51l(Fetch16(0));
319 }
320
321 // The following methods return the vA operand for various instruction formats. The "inst_data"
322 // parameter holds the first 16 bits of instruction which the returned value is decoded from.
323 int8_t VRegA_10t(uint16_t inst_data) const;
324 uint8_t VRegA_10x(uint16_t inst_data) const;
325 uint4_t VRegA_11n(uint16_t inst_data) const;
326 uint8_t VRegA_11x(uint16_t inst_data) const;
327 uint4_t VRegA_12x(uint16_t inst_data) const;
328 uint8_t VRegA_21c(uint16_t inst_data) const;
329 uint8_t VRegA_21h(uint16_t inst_data) const;
330 uint8_t VRegA_21s(uint16_t inst_data) const;
331 uint8_t VRegA_21t(uint16_t inst_data) const;
332 uint8_t VRegA_22b(uint16_t inst_data) const;
333 uint4_t VRegA_22c(uint16_t inst_data) const;
334 uint4_t VRegA_22s(uint16_t inst_data) const;
335 uint4_t VRegA_22t(uint16_t inst_data) const;
336 uint8_t VRegA_22x(uint16_t inst_data) const;
337 uint8_t VRegA_23x(uint16_t inst_data) const;
338 uint8_t VRegA_31c(uint16_t inst_data) const;
339 uint8_t VRegA_31i(uint16_t inst_data) const;
340 uint8_t VRegA_31t(uint16_t inst_data) const;
341 uint4_t VRegA_35c(uint16_t inst_data) const;
342 uint8_t VRegA_3rc(uint16_t inst_data) const;
343 uint8_t VRegA_51l(uint16_t inst_data) const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200344
345 // VRegB
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700346 bool HasVRegB() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700347 int32_t VRegB() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200348
Ian Rogers29a26482014-05-02 15:27:29 -0700349 bool HasWideVRegB() const;
350 uint64_t WideVRegB() const;
351
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200352 int4_t VRegB_11n() const {
353 return VRegB_11n(Fetch16(0));
354 }
355 uint4_t VRegB_12x() const {
356 return VRegB_12x(Fetch16(0));
357 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200358 uint16_t VRegB_21c() const;
359 uint16_t VRegB_21h() const;
360 int16_t VRegB_21s() const;
361 int16_t VRegB_21t() const;
362 uint8_t VRegB_22b() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200363 uint4_t VRegB_22c() const {
364 return VRegB_22c(Fetch16(0));
365 }
366 uint4_t VRegB_22s() const {
367 return VRegB_22s(Fetch16(0));
368 }
369 uint4_t VRegB_22t() const {
370 return VRegB_22t(Fetch16(0));
371 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200372 uint16_t VRegB_22x() const;
373 uint8_t VRegB_23x() const;
Igor Murashkin158f35c2015-06-10 15:55:30 -0700374 uint4_t VRegB_25x() const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200375 uint32_t VRegB_31c() const;
376 int32_t VRegB_31i() const;
377 int32_t VRegB_31t() const;
378 uint16_t VRegB_32x() const;
379 uint16_t VRegB_35c() const;
380 uint16_t VRegB_3rc() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700381 uint64_t VRegB_51l() const; // vB_wide
Sebastien Hertz807a2562013-04-15 09:33:39 +0200382
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200383 // The following methods return the vB operand for all instruction formats where it is encoded in
384 // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
385 // value is decoded from it.
386 int4_t VRegB_11n(uint16_t inst_data) const;
387 uint4_t VRegB_12x(uint16_t inst_data) const;
388 uint4_t VRegB_22c(uint16_t inst_data) const;
389 uint4_t VRegB_22s(uint16_t inst_data) const;
390 uint4_t VRegB_22t(uint16_t inst_data) const;
391
Sebastien Hertz807a2562013-04-15 09:33:39 +0200392 // VRegC
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700393 bool HasVRegC() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700394 int32_t VRegC() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200395
Sebastien Hertz807a2562013-04-15 09:33:39 +0200396 int8_t VRegC_22b() const;
397 uint16_t VRegC_22c() const;
398 int16_t VRegC_22s() const;
399 int16_t VRegC_22t() const;
400 uint8_t VRegC_23x() const;
Igor Murashkin158f35c2015-06-10 15:55:30 -0700401 uint4_t VRegC_25x() const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200402 uint4_t VRegC_35c() const;
403 uint16_t VRegC_3rc() const;
404
405 // Fills the given array with the 'arg' array of the instruction.
Igor Murashkin158f35c2015-06-10 15:55:30 -0700406 bool HasVarArgs35c() const;
407 bool HasVarArgs25x() const;
408
409 // TODO(iam): Make this name more consistent with GetAllArgs25x by including the opcode format.
Ian Rogers29a26482014-05-02 15:27:29 -0700410 void GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
411 void GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
412 return GetVarArgs(args, Fetch16(0));
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200413 }
Igor Murashkin6918bf12015-09-27 19:19:06 -0700414 void GetAllArgs25x(uint32_t (&args)[kMaxVarArgRegs25x]) const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200415
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200416 // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
417 // 16 bits of instruction.
418 Code Opcode(uint16_t inst_data) const {
419 DCHECK_EQ(inst_data, Fetch16(0));
420 return static_cast<Code>(inst_data & 0xFF);
421 }
422
423 // Returns the opcode field of the instruction from the first 16 bits of instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700424 Code Opcode() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200425 return Opcode(Fetch16(0));
Ian Rogersa75a0132012-09-28 11:41:42 -0700426 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700427
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200428 void SetOpcode(Code opcode) {
429 DCHECK_LT(static_cast<uint16_t>(opcode), 256u);
430 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
431 insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode);
432 }
433
Sebastien Hertz543959c2013-07-03 12:00:19 +0200434 void SetVRegA_10x(uint8_t val) {
435 DCHECK(FormatOf(Opcode()) == k10x);
436 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
437 insns[0] = (val << 8) | (insns[0] & 0x00ff);
438 }
439
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200440 void SetVRegB_3rc(uint16_t val) {
441 DCHECK(FormatOf(Opcode()) == k3rc);
442 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
443 insns[1] = val;
444 }
445
446 void SetVRegB_35c(uint16_t val) {
447 DCHECK(FormatOf(Opcode()) == k35c);
448 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
449 insns[1] = val;
450 }
451
452 void SetVRegC_22c(uint16_t val) {
453 DCHECK(FormatOf(Opcode()) == k22c);
454 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
455 insns[1] = val;
456 }
457
Elliott Hughesadb8c672012-03-06 16:49:32 -0800458 // Returns the format of the given opcode.
459 static Format FormatOf(Code opcode) {
460 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700461 }
462
Aart Bikb1f37532015-06-29 11:03:55 -0700463 // Returns the index type of the given opcode.
464 static IndexType IndexTypeOf(Code opcode) {
465 return kInstructionIndexTypes[opcode];
466 }
467
Elliott Hughesadb8c672012-03-06 16:49:32 -0800468 // Returns the flags for the given opcode.
Ian Rogersa75a0132012-09-28 11:41:42 -0700469 static int FlagsOf(Code opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800470 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700471 }
472
buzbeeb1f1d642014-02-27 12:55:32 -0800473 // Return the verify flags for the given opcode.
474 static int VerifyFlagsOf(Code opcode) {
475 return kInstructionVerifyFlags[opcode];
476 }
477
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700478 // Returns true if this instruction is a branch.
479 bool IsBranch() const {
480 return (kInstructionFlags[Opcode()] & kBranch) != 0;
481 }
482
TDYa127526643e2012-05-26 01:01:48 -0700483 // Returns true if this instruction is a unconditional branch.
484 bool IsUnconditional() const {
485 return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
486 }
487
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700488 // Returns the branch offset if this instruction is a branch.
489 int32_t GetTargetOffset() const;
490
491 // Returns true if the instruction allows control flow to go to the following instruction.
492 bool CanFlowThrough() const;
493
Nicolas Geoffray9523a3e2015-07-17 11:51:28 +0000494 // Returns true if the instruction is a quickened instruction.
495 bool IsQuickened() const {
496 return (kInstructionIndexTypes[Opcode()] == kIndexFieldOffset) ||
497 (kInstructionIndexTypes[Opcode()] == kIndexVtableOffset);
498 }
499
jeffhaoba5ebb92011-08-25 17:24:37 -0700500 // Returns true if this instruction is a switch.
501 bool IsSwitch() const {
502 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
503 }
504
505 // Returns true if this instruction can throw.
506 bool IsThrow() const {
507 return (kInstructionFlags[Opcode()] & kThrow) != 0;
508 }
509
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700510 // Determine if the instruction is any of 'return' instructions.
511 bool IsReturn() const {
512 return (kInstructionFlags[Opcode()] & kReturn) != 0;
513 }
514
515 // Determine if this instruction ends execution of its basic block.
516 bool IsBasicBlockEnd() const {
517 return IsBranch() || IsReturn() || Opcode() == THROW;
518 }
519
520 // Determine if this instruction is an invoke.
521 bool IsInvoke() const {
522 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
523 }
524
Igor Murashkin158f35c2015-06-10 15:55:30 -0700525 // Determine if this instruction is experimental.
526 bool IsExperimental() const {
527 return (kInstructionFlags[Opcode()] & kExperimental) != 0;
528 }
529
jeffhaoba5ebb92011-08-25 17:24:37 -0700530 int GetVerifyTypeArgumentA() const {
531 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
532 }
533
534 int GetVerifyTypeArgumentB() const {
Ian Rogers5fb22a92014-06-13 10:31:28 -0700535 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField |
536 kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType |
537 kVerifyRegBWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700538 }
539
540 int GetVerifyTypeArgumentC() const {
541 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
Igor Murashkin6918bf12015-09-27 19:19:06 -0700542 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide | kVerifyRegCString));
jeffhaoba5ebb92011-08-25 17:24:37 -0700543 }
544
545 int GetVerifyExtraFlags() const {
546 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
Andreas Gampec3314312014-06-19 18:13:29 -0700547 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | kVerifyVarArgRange |
548 kVerifyVarArgRangeNonZero | kVerifyError));
Ian Rogers5fb22a92014-06-13 10:31:28 -0700549 }
550
551 bool GetVerifyIsRuntimeOnly() const {
552 return (kInstructionVerifyFlags[Opcode()] & kVerifyRuntimeOnly) != 0;
jeffhaoba5ebb92011-08-25 17:24:37 -0700553 }
554
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700555 // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
556 uint32_t GetDexPc(const uint16_t* insns) const {
557 return (reinterpret_cast<const uint16_t*>(this) - insns);
558 }
559
Ian Rogersd81871c2011-10-03 13:57:23 -0700560 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700561 std::string DumpString(const DexFile*) const;
562
563 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
564 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700565
Anestis Bechtsoudis32f500d2015-02-22 22:32:57 -0800566 // Little-endian dump code_units worth of this instruction, padding to code_units for
567 // shorter instructions
568 std::string DumpHexLE(size_t instr_code_units) const;
569
Sebastien Hertz807a2562013-04-15 09:33:39 +0200570 uint16_t Fetch16(size_t offset) const {
571 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
572 return insns[offset];
573 }
574
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200575 private:
576 size_t SizeInCodeUnitsComplexOpcode() const;
577
Sebastien Hertz807a2562013-04-15 09:33:39 +0200578 uint32_t Fetch32(size_t offset) const {
579 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
580 }
581
582 uint4_t InstA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200583 return InstA(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200584 }
585
586 uint4_t InstB() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200587 return InstB(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200588 }
589
590 uint8_t InstAA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200591 return InstAA(Fetch16(0));
592 }
593
594 uint4_t InstA(uint16_t inst_data) const {
595 DCHECK_EQ(inst_data, Fetch16(0));
596 return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
597 }
598
599 uint4_t InstB(uint16_t inst_data) const {
600 DCHECK_EQ(inst_data, Fetch16(0));
601 return static_cast<uint4_t>(inst_data >> 12);
602 }
603
604 uint8_t InstAA(uint16_t inst_data) const {
605 DCHECK_EQ(inst_data, Fetch16(0));
606 return static_cast<uint8_t>(inst_data >> 8);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200607 }
608
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700609 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800610 static Format const kInstructionFormats[];
Aart Bikb1f37532015-06-29 11:03:55 -0700611 static IndexType const kInstructionIndexTypes[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700612 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700613 static int const kInstructionVerifyFlags[];
Ian Rogersa75a0132012-09-28 11:41:42 -0700614 static int const kInstructionSizeInCodeUnits[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700615 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
616};
Ian Rogersa75a0132012-09-28 11:41:42 -0700617std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
618std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
619std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
620std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800621
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700622} // namespace art
623
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700624#endif // ART_RUNTIME_DEX_INSTRUCTION_H_