blob: 1ff5c196b022616c96ed7d81b213709a0cc84657 [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.
38 enum {
39 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 Rogersa75a0132012-09-28 11:41:42 -070082 // TODO: the code layout below is deliberate to avoid this enum being picked up by
83 // generate-operator-out.py.
84 enum Code
Brian Carlstrom7934ac22013-07-26 10:54:15 -070085 { // NOLINT(whitespace/braces)
jeffhaoba5ebb92011-08-25 17:24:37 -070086#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070087#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070088 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070089#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070090#undef INSTRUCTION_ENUM
Brian Carlstrom02c8cc62013-07-18 15:54:44 -070091 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070092
Elliott Hughesadb8c672012-03-06 16:49:32 -080093 enum Format {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070094 k10x, // op
95 k12x, // op vA, vB
96 k11n, // op vA, #+B
97 k11x, // op vAA
98 k10t, // op +AA
99 k20t, // op +AAAA
100 k22x, // op vAA, vBBBB
101 k21t, // op vAA, +BBBB
102 k21s, // op vAA, #+BBBB
103 k21h, // op vAA, #+BBBB00000[00000000]
104 k21c, // op vAA, thing@BBBB
105 k23x, // op vAA, vBB, vCC
106 k22b, // op vAA, vBB, #+CC
107 k22t, // op vA, vB, +CCCC
108 k22s, // op vA, vB, #+CCCC
109 k22c, // op vA, vB, thing@CCCC
110 k32x, // op vAAAA, vBBBB
111 k30t, // op +AAAAAAAA
112 k31t, // op vAA, +BBBBBBBB
113 k31i, // op vAA, #+BBBBBBBB
114 k31c, // op vAA, thing@BBBBBBBB
115 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
116 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
117 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
118 };
119
120 enum Flags {
Jean Christophe Beylerc3db20b2014-05-05 21:09:40 -0700121 kBranch = 0x000001, // conditional or unconditional branch
122 kContinue = 0x000002, // flow can continue to next statement
123 kSwitch = 0x000004, // switch statement
124 kThrow = 0x000008, // could cause an exception to be thrown
125 kReturn = 0x000010, // returns, no additional statements
126 kInvoke = 0x000020, // a flavor of invoke
127 kUnconditional = 0x000040, // unconditional branch
128 kAdd = 0x000080, // addition
129 kSubtract = 0x000100, // subtract
130 kMultiply = 0x000200, // multiply
131 kDivide = 0x000400, // division
132 kRemainder = 0x000800, // remainder
133 kAnd = 0x001000, // and
134 kOr = 0x002000, // or
135 kXor = 0x004000, // xor
136 kShl = 0x008000, // shl
137 kShr = 0x010000, // shr
138 kUshr = 0x020000, // ushr
139 kCast = 0x040000, // cast
140 kStore = 0x080000, // store opcode
141 kLoad = 0x100000, // load opcode
142 kClobber = 0x200000, // clobbers memory in a big way (not just a write)
143 kRegCFieldOrConstant = 0x400000, // is the third virtual register a field or literal constant (vC)
144 kRegBFieldOrConstant = 0x800000, // is the second virtual register a field or literal constant (vB)
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700145 };
146
jeffhaoba5ebb92011-08-25 17:24:37 -0700147 enum VerifyFlag {
148 kVerifyNone = 0x00000,
149 kVerifyRegA = 0x00001,
150 kVerifyRegAWide = 0x00002,
151 kVerifyRegB = 0x00004,
152 kVerifyRegBField = 0x00008,
153 kVerifyRegBMethod = 0x00010,
154 kVerifyRegBNewInstance = 0x00020,
155 kVerifyRegBString = 0x00040,
156 kVerifyRegBType = 0x00080,
157 kVerifyRegBWide = 0x00100,
158 kVerifyRegC = 0x00200,
159 kVerifyRegCField = 0x00400,
160 kVerifyRegCNewArray = 0x00800,
161 kVerifyRegCType = 0x01000,
162 kVerifyRegCWide = 0x02000,
163 kVerifyArrayData = 0x04000,
164 kVerifyBranchTarget = 0x08000,
165 kVerifySwitchTargets = 0x10000,
166 kVerifyVarArg = 0x20000,
167 kVerifyVarArgRange = 0x40000,
168 kVerifyError = 0x80000,
169 };
170
Ian Rogers29a26482014-05-02 15:27:29 -0700171 static constexpr uint32_t kMaxVarArgRegs = 5;
jeffhaoba5ebb92011-08-25 17:24:37 -0700172
Elliott Hughesadb8c672012-03-06 16:49:32 -0800173 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700174 size_t SizeInCodeUnits() const {
175 int result = kInstructionSizeInCodeUnits[Opcode()];
176 if (UNLIKELY(result < 0)) {
177 return SizeInCodeUnitsComplexOpcode();
178 } else {
179 return static_cast<size_t>(result);
180 }
181 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700182
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200183 // Reads an instruction out of the stream at the specified address.
184 static const Instruction* At(const uint16_t* code) {
185 DCHECK(code != NULL);
186 return reinterpret_cast<const Instruction*>(code);
187 }
188
189 // Reads an instruction out of the stream from the current address plus an offset.
190 const Instruction* RelativeAt(int32_t offset) const {
191 return At(reinterpret_cast<const uint16_t*>(this) + offset);
192 }
193
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700194 // Returns a pointer to the next instruction in the stream.
Ian Rogersa75a0132012-09-28 11:41:42 -0700195 const Instruction* Next() const {
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200196 return RelativeAt(SizeInCodeUnits());
Ian Rogersa75a0132012-09-28 11:41:42 -0700197 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700198
Jeff Hao9cec2472013-05-14 18:17:06 -0700199 // Returns a pointer to the instruction after this 1xx instruction in the stream.
200 const Instruction* Next_1xx() const {
201 DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200202 return RelativeAt(1);
Jeff Hao9cec2472013-05-14 18:17:06 -0700203 }
204
205 // Returns a pointer to the instruction after this 2xx instruction in the stream.
206 const Instruction* Next_2xx() const {
207 DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200208 return RelativeAt(2);
Jeff Hao9cec2472013-05-14 18:17:06 -0700209 }
210
211 // Returns a pointer to the instruction after this 3xx instruction in the stream.
212 const Instruction* Next_3xx() const {
213 DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200214 return RelativeAt(3);
Jeff Hao9cec2472013-05-14 18:17:06 -0700215 }
216
217 // Returns a pointer to the instruction after this 51l instruction in the stream.
Sebastien Hertz92c607f2013-06-04 16:18:52 +0200218 const Instruction* Next_51l() const {
219 DCHECK(FormatOf(Opcode()) == k51l);
220 return RelativeAt(5);
221 }
Jeff Hao9cec2472013-05-14 18:17:06 -0700222
Elliott Hughesadb8c672012-03-06 16:49:32 -0800223 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700224 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800225 return Instruction::Name(Opcode());
226 }
227
228 // Returns the name of the given opcode.
229 static const char* Name(Code opcode) {
230 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700231 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700232
Sebastien Hertz807a2562013-04-15 09:33:39 +0200233 // VRegA
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700234 bool HasVRegA() const;
Dragos Sbirlead25de7a2013-06-21 09:20:34 -0700235 int32_t VRegA() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200236
237 int8_t VRegA_10t() const {
238 return VRegA_10t(Fetch16(0));
239 }
240 uint8_t VRegA_10x() const {
241 return VRegA_10x(Fetch16(0));
242 }
243 uint4_t VRegA_11n() const {
244 return VRegA_11n(Fetch16(0));
245 }
246 uint8_t VRegA_11x() const {
247 return VRegA_11x(Fetch16(0));
248 }
249 uint4_t VRegA_12x() const {
250 return VRegA_12x(Fetch16(0));
251 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200252 int16_t VRegA_20t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200253 uint8_t VRegA_21c() const {
254 return VRegA_21c(Fetch16(0));
255 }
256 uint8_t VRegA_21h() const {
257 return VRegA_21h(Fetch16(0));
258 }
259 uint8_t VRegA_21s() const {
260 return VRegA_21s(Fetch16(0));
261 }
262 uint8_t VRegA_21t() const {
263 return VRegA_21t(Fetch16(0));
264 }
265 uint8_t VRegA_22b() const {
266 return VRegA_22b(Fetch16(0));
267 }
268 uint4_t VRegA_22c() const {
269 return VRegA_22c(Fetch16(0));
270 }
271 uint4_t VRegA_22s() const {
272 return VRegA_22s(Fetch16(0));
273 }
274 uint4_t VRegA_22t() const {
275 return VRegA_22t(Fetch16(0));
276 }
277 uint8_t VRegA_22x() const {
278 return VRegA_22x(Fetch16(0));
279 }
280 uint8_t VRegA_23x() const {
281 return VRegA_23x(Fetch16(0));
282 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200283 int32_t VRegA_30t() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200284 uint8_t VRegA_31c() const {
285 return VRegA_31c(Fetch16(0));
286 }
287 uint8_t VRegA_31i() const {
288 return VRegA_31i(Fetch16(0));
289 }
290 uint8_t VRegA_31t() const {
291 return VRegA_31t(Fetch16(0));
292 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200293 uint16_t VRegA_32x() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200294 uint4_t VRegA_35c() const {
295 return VRegA_35c(Fetch16(0));
296 }
297 uint8_t VRegA_3rc() const {
298 return VRegA_3rc(Fetch16(0));
299 }
300 uint8_t VRegA_51l() const {
301 return VRegA_51l(Fetch16(0));
302 }
303
304 // The following methods return the vA operand for various instruction formats. The "inst_data"
305 // parameter holds the first 16 bits of instruction which the returned value is decoded from.
306 int8_t VRegA_10t(uint16_t inst_data) const;
307 uint8_t VRegA_10x(uint16_t inst_data) const;
308 uint4_t VRegA_11n(uint16_t inst_data) const;
309 uint8_t VRegA_11x(uint16_t inst_data) const;
310 uint4_t VRegA_12x(uint16_t inst_data) const;
311 uint8_t VRegA_21c(uint16_t inst_data) const;
312 uint8_t VRegA_21h(uint16_t inst_data) const;
313 uint8_t VRegA_21s(uint16_t inst_data) const;
314 uint8_t VRegA_21t(uint16_t inst_data) const;
315 uint8_t VRegA_22b(uint16_t inst_data) const;
316 uint4_t VRegA_22c(uint16_t inst_data) const;
317 uint4_t VRegA_22s(uint16_t inst_data) const;
318 uint4_t VRegA_22t(uint16_t inst_data) const;
319 uint8_t VRegA_22x(uint16_t inst_data) const;
320 uint8_t VRegA_23x(uint16_t inst_data) const;
321 uint8_t VRegA_31c(uint16_t inst_data) const;
322 uint8_t VRegA_31i(uint16_t inst_data) const;
323 uint8_t VRegA_31t(uint16_t inst_data) const;
324 uint4_t VRegA_35c(uint16_t inst_data) const;
325 uint8_t VRegA_3rc(uint16_t inst_data) const;
326 uint8_t VRegA_51l(uint16_t inst_data) const;
Sebastien Hertz807a2562013-04-15 09:33:39 +0200327
328 // VRegB
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700329 bool HasVRegB() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700330 int32_t VRegB() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200331
Ian Rogers29a26482014-05-02 15:27:29 -0700332 bool HasWideVRegB() const;
333 uint64_t WideVRegB() const;
334
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200335 int4_t VRegB_11n() const {
336 return VRegB_11n(Fetch16(0));
337 }
338 uint4_t VRegB_12x() const {
339 return VRegB_12x(Fetch16(0));
340 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200341 uint16_t VRegB_21c() const;
342 uint16_t VRegB_21h() const;
343 int16_t VRegB_21s() const;
344 int16_t VRegB_21t() const;
345 uint8_t VRegB_22b() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200346 uint4_t VRegB_22c() const {
347 return VRegB_22c(Fetch16(0));
348 }
349 uint4_t VRegB_22s() const {
350 return VRegB_22s(Fetch16(0));
351 }
352 uint4_t VRegB_22t() const {
353 return VRegB_22t(Fetch16(0));
354 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200355 uint16_t VRegB_22x() const;
356 uint8_t VRegB_23x() const;
357 uint32_t VRegB_31c() const;
358 int32_t VRegB_31i() const;
359 int32_t VRegB_31t() const;
360 uint16_t VRegB_32x() const;
361 uint16_t VRegB_35c() const;
362 uint16_t VRegB_3rc() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700363 uint64_t VRegB_51l() const; // vB_wide
Sebastien Hertz807a2562013-04-15 09:33:39 +0200364
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200365 // The following methods return the vB operand for all instruction formats where it is encoded in
366 // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
367 // value is decoded from it.
368 int4_t VRegB_11n(uint16_t inst_data) const;
369 uint4_t VRegB_12x(uint16_t inst_data) const;
370 uint4_t VRegB_22c(uint16_t inst_data) const;
371 uint4_t VRegB_22s(uint16_t inst_data) const;
372 uint4_t VRegB_22t(uint16_t inst_data) const;
373
Sebastien Hertz807a2562013-04-15 09:33:39 +0200374 // VRegC
Dragos Sbirlea8cc51622013-06-21 09:20:34 -0700375 bool HasVRegC() const;
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700376 int32_t VRegC() const;
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200377
Sebastien Hertz807a2562013-04-15 09:33:39 +0200378 int8_t VRegC_22b() const;
379 uint16_t VRegC_22c() const;
380 int16_t VRegC_22s() const;
381 int16_t VRegC_22t() const;
382 uint8_t VRegC_23x() const;
383 uint4_t VRegC_35c() const;
384 uint16_t VRegC_3rc() const;
385
386 // Fills the given array with the 'arg' array of the instruction.
Ian Rogers29a26482014-05-02 15:27:29 -0700387 bool HasVarArgs() const;
388 void GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
389 void GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
390 return GetVarArgs(args, Fetch16(0));
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200391 }
Sebastien Hertz807a2562013-04-15 09:33:39 +0200392
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200393 // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
394 // 16 bits of instruction.
395 Code Opcode(uint16_t inst_data) const {
396 DCHECK_EQ(inst_data, Fetch16(0));
397 return static_cast<Code>(inst_data & 0xFF);
398 }
399
400 // Returns the opcode field of the instruction from the first 16 bits of instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700401 Code Opcode() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200402 return Opcode(Fetch16(0));
Ian Rogersa75a0132012-09-28 11:41:42 -0700403 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700404
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200405 void SetOpcode(Code opcode) {
406 DCHECK_LT(static_cast<uint16_t>(opcode), 256u);
407 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
408 insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode);
409 }
410
Sebastien Hertz543959c2013-07-03 12:00:19 +0200411 void SetVRegA_10x(uint8_t val) {
412 DCHECK(FormatOf(Opcode()) == k10x);
413 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
414 insns[0] = (val << 8) | (insns[0] & 0x00ff);
415 }
416
Sebastien Hertz2d6ba512013-05-17 11:31:37 +0200417 void SetVRegB_3rc(uint16_t val) {
418 DCHECK(FormatOf(Opcode()) == k3rc);
419 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
420 insns[1] = val;
421 }
422
423 void SetVRegB_35c(uint16_t val) {
424 DCHECK(FormatOf(Opcode()) == k35c);
425 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
426 insns[1] = val;
427 }
428
429 void SetVRegC_22c(uint16_t val) {
430 DCHECK(FormatOf(Opcode()) == k22c);
431 uint16_t* insns = reinterpret_cast<uint16_t*>(this);
432 insns[1] = val;
433 }
434
Elliott Hughesadb8c672012-03-06 16:49:32 -0800435 // Returns the format of the given opcode.
436 static Format FormatOf(Code opcode) {
437 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700438 }
439
Elliott Hughesadb8c672012-03-06 16:49:32 -0800440 // Returns the flags for the given opcode.
Ian Rogersa75a0132012-09-28 11:41:42 -0700441 static int FlagsOf(Code opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800442 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700443 }
444
buzbeeb1f1d642014-02-27 12:55:32 -0800445 // Return the verify flags for the given opcode.
446 static int VerifyFlagsOf(Code opcode) {
447 return kInstructionVerifyFlags[opcode];
448 }
449
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700450 // Returns true if this instruction is a branch.
451 bool IsBranch() const {
452 return (kInstructionFlags[Opcode()] & kBranch) != 0;
453 }
454
TDYa127526643e2012-05-26 01:01:48 -0700455 // Returns true if this instruction is a unconditional branch.
456 bool IsUnconditional() const {
457 return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
458 }
459
Dragos Sbirlea39f99272013-06-25 13:17:36 -0700460 // Returns the branch offset if this instruction is a branch.
461 int32_t GetTargetOffset() const;
462
463 // Returns true if the instruction allows control flow to go to the following instruction.
464 bool CanFlowThrough() const;
465
jeffhaoba5ebb92011-08-25 17:24:37 -0700466 // Returns true if this instruction is a switch.
467 bool IsSwitch() const {
468 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
469 }
470
471 // Returns true if this instruction can throw.
472 bool IsThrow() const {
473 return (kInstructionFlags[Opcode()] & kThrow) != 0;
474 }
475
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700476 // Determine if the instruction is any of 'return' instructions.
477 bool IsReturn() const {
478 return (kInstructionFlags[Opcode()] & kReturn) != 0;
479 }
480
481 // Determine if this instruction ends execution of its basic block.
482 bool IsBasicBlockEnd() const {
483 return IsBranch() || IsReturn() || Opcode() == THROW;
484 }
485
486 // Determine if this instruction is an invoke.
487 bool IsInvoke() const {
488 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
489 }
490
jeffhaoba5ebb92011-08-25 17:24:37 -0700491 int GetVerifyTypeArgumentA() const {
492 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
493 }
494
495 int GetVerifyTypeArgumentB() const {
496 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
497 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
498 }
499
500 int GetVerifyTypeArgumentC() const {
501 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
jeffhao3bb32462012-02-01 16:12:27 -0800502 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700503 }
504
505 int GetVerifyExtraFlags() const {
506 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
507 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
508 }
509
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700510 // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
511 uint32_t GetDexPc(const uint16_t* insns) const {
512 return (reinterpret_cast<const uint16_t*>(this) - insns);
513 }
514
Ian Rogersd81871c2011-10-03 13:57:23 -0700515 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700516 std::string DumpString(const DexFile*) const;
517
518 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
519 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700520
Sebastien Hertz807a2562013-04-15 09:33:39 +0200521 uint16_t Fetch16(size_t offset) const {
522 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
523 return insns[offset];
524 }
525
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200526 private:
527 size_t SizeInCodeUnitsComplexOpcode() const;
528
Sebastien Hertz807a2562013-04-15 09:33:39 +0200529 uint32_t Fetch32(size_t offset) const {
530 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
531 }
532
533 uint4_t InstA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200534 return InstA(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200535 }
536
537 uint4_t InstB() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200538 return InstB(Fetch16(0));
Sebastien Hertz807a2562013-04-15 09:33:39 +0200539 }
540
541 uint8_t InstAA() const {
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200542 return InstAA(Fetch16(0));
543 }
544
545 uint4_t InstA(uint16_t inst_data) const {
546 DCHECK_EQ(inst_data, Fetch16(0));
547 return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
548 }
549
550 uint4_t InstB(uint16_t inst_data) const {
551 DCHECK_EQ(inst_data, Fetch16(0));
552 return static_cast<uint4_t>(inst_data >> 12);
553 }
554
555 uint8_t InstAA(uint16_t inst_data) const {
556 DCHECK_EQ(inst_data, Fetch16(0));
557 return static_cast<uint8_t>(inst_data >> 8);
Sebastien Hertz807a2562013-04-15 09:33:39 +0200558 }
559
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700560 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800561 static Format const kInstructionFormats[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700562 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700563 static int const kInstructionVerifyFlags[];
Ian Rogersa75a0132012-09-28 11:41:42 -0700564 static int const kInstructionSizeInCodeUnits[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700565 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
566};
Ian Rogersa75a0132012-09-28 11:41:42 -0700567std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
568std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
569std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
570std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800571
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700572} // namespace art
573
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700574#endif // ART_RUNTIME_DEX_INSTRUCTION_H_