blob: 45c93ef3c7379fbc91b4ebd4dc76fe60903e6404 [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
17#ifndef ART_SRC_DEX_INSTRUCTION_H_
18#define ART_SRC_DEX_INSTRUCTION_H_
19
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[];
49 private:
50 DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
51 };
52
Ian Rogersdf1ce912012-11-27 17:07:11 -080053 struct PACKED(4) SparseSwitchPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080054 const uint16_t ident;
55 const uint16_t case_count;
56 const int32_t keys_and_targets[];
57
58 public:
59 const int32_t* GetKeys() const {
60 return keys_and_targets;
61 }
62
63 const int32_t* GetTargets() const {
64 return keys_and_targets + case_count;
65 }
66
67 private:
68 DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
69 };
70
Ian Rogersdf1ce912012-11-27 17:07:11 -080071 struct PACKED(4) ArrayDataPayload {
Logan Chien19c350a2012-05-01 19:21:32 +080072 const uint16_t ident;
73 const uint16_t element_width;
74 const uint32_t element_count;
75 const uint8_t data[];
76 private:
77 DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
78 };
79
Ian Rogersa75a0132012-09-28 11:41:42 -070080 // TODO: the code layout below is deliberate to avoid this enum being picked up by
81 // generate-operator-out.py.
82 enum Code
83 {
jeffhaoba5ebb92011-08-25 17:24:37 -070084#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, 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 Rogersa75a0132012-09-28 11:41:42 -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
108 k32x, // op vAAAA, vBBBB
109 k30t, // op +AAAAAAAA
110 k31t, // op vAA, +BBBBBBBB
111 k31i, // op vAA, #+BBBBBBBB
112 k31c, // op vAA, thing@BBBBBBBB
113 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
114 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
115 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
116 };
117
118 enum Flags {
119 kBranch = 0x01, // conditional or unconditional branch
120 kContinue = 0x02, // flow can continue to next statement
121 kSwitch = 0x04, // switch statement
122 kThrow = 0x08, // could cause an exception to be thrown
123 kReturn = 0x10, // returns, no additional statements
124 kInvoke = 0x20, // a flavor of invoke
TDYa127526643e2012-05-26 01:01:48 -0700125 kUnconditional = 0x40, // unconditional branch
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700126 };
127
jeffhaoba5ebb92011-08-25 17:24:37 -0700128 enum VerifyFlag {
129 kVerifyNone = 0x00000,
130 kVerifyRegA = 0x00001,
131 kVerifyRegAWide = 0x00002,
132 kVerifyRegB = 0x00004,
133 kVerifyRegBField = 0x00008,
134 kVerifyRegBMethod = 0x00010,
135 kVerifyRegBNewInstance = 0x00020,
136 kVerifyRegBString = 0x00040,
137 kVerifyRegBType = 0x00080,
138 kVerifyRegBWide = 0x00100,
139 kVerifyRegC = 0x00200,
140 kVerifyRegCField = 0x00400,
141 kVerifyRegCNewArray = 0x00800,
142 kVerifyRegCType = 0x01000,
143 kVerifyRegCWide = 0x02000,
144 kVerifyArrayData = 0x04000,
145 kVerifyBranchTarget = 0x08000,
146 kVerifySwitchTargets = 0x10000,
147 kVerifyVarArg = 0x20000,
148 kVerifyVarArgRange = 0x40000,
149 kVerifyError = 0x80000,
150 };
151
152 // Decodes this instruction, populating its arguments.
153 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
154
Elliott Hughesadb8c672012-03-06 16:49:32 -0800155 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700156 size_t SizeInCodeUnits() const {
157 int result = kInstructionSizeInCodeUnits[Opcode()];
158 if (UNLIKELY(result < 0)) {
159 return SizeInCodeUnitsComplexOpcode();
160 } else {
161 return static_cast<size_t>(result);
162 }
163 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700164
165 // Returns a pointer to the next instruction in the stream.
Ian Rogersa75a0132012-09-28 11:41:42 -0700166 const Instruction* Next() const {
167 size_t current_size_in_bytes = SizeInCodeUnits() * sizeof(uint16_t);
168 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(this);
169 return reinterpret_cast<const Instruction*>(ptr + current_size_in_bytes);
170 }
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700171
Elliott Hughesadb8c672012-03-06 16:49:32 -0800172 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700173 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800174 return Instruction::Name(Opcode());
175 }
176
177 // Returns the name of the given opcode.
178 static const char* Name(Code opcode) {
179 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700180 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700181
Sebastien Hertz807a2562013-04-15 09:33:39 +0200182 // VRegA
183 int8_t VRegA_10t() const;
184 uint4_t VRegA_11n() const;
185 uint8_t VRegA_11x() const;
186 uint4_t VRegA_12x() const;
187 int16_t VRegA_20t() const;
188 uint8_t VRegA_21c() const;
189 uint8_t VRegA_21h() const;
190 uint8_t VRegA_21s() const;
191 uint8_t VRegA_21t() const;
192 uint8_t VRegA_22b() const;
193 uint4_t VRegA_22c() const;
194 uint4_t VRegA_22s() const;
195 uint4_t VRegA_22t() const;
196 uint8_t VRegA_22x() const;
197 uint8_t VRegA_23x() const;
198 int32_t VRegA_30t() const;
199 uint8_t VRegA_31c() const;
200 uint8_t VRegA_31i() const;
201 uint8_t VRegA_31t() const;
202 uint16_t VRegA_32x() const;
203 uint4_t VRegA_35c() const;
204 uint8_t VRegA_3rc() const;
205 uint8_t VRegA_51l() const;
206
207 // VRegB
208 int4_t VRegB_11n() const;
209 uint4_t VRegB_12x() const;
210 uint16_t VRegB_21c() const;
211 uint16_t VRegB_21h() const;
212 int16_t VRegB_21s() const;
213 int16_t VRegB_21t() const;
214 uint8_t VRegB_22b() const;
215 uint4_t VRegB_22c() const;
216 uint4_t VRegB_22s() const;
217 uint4_t VRegB_22t() const;
218 uint16_t VRegB_22x() const;
219 uint8_t VRegB_23x() const;
220 uint32_t VRegB_31c() const;
221 int32_t VRegB_31i() const;
222 int32_t VRegB_31t() const;
223 uint16_t VRegB_32x() const;
224 uint16_t VRegB_35c() const;
225 uint16_t VRegB_3rc() const;
226 uint64_t VRegB_51l() const; // vB_wide
227
228 // VRegC
229 int8_t VRegC_22b() const;
230 uint16_t VRegC_22c() const;
231 int16_t VRegC_22s() const;
232 int16_t VRegC_22t() const;
233 uint8_t VRegC_23x() const;
234 uint4_t VRegC_35c() const;
235 uint16_t VRegC_3rc() const;
236
237 // Fills the given array with the 'arg' array of the instruction.
238 void GetArgs(uint32_t args[5]) const;
239
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700240 // Returns the opcode field of the instruction.
Ian Rogersa75a0132012-09-28 11:41:42 -0700241 Code Opcode() const {
242 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
243 int opcode = *insns & 0xFF;
244 return static_cast<Code>(opcode);
245 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700246
247 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700248 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700249 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700250 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700251 }
252
Elliott Hughesadb8c672012-03-06 16:49:32 -0800253 // Returns the format of the given opcode.
254 static Format FormatOf(Code opcode) {
255 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700256 }
257
Elliott Hughesadb8c672012-03-06 16:49:32 -0800258 // Returns the flags for the given opcode.
Ian Rogersa75a0132012-09-28 11:41:42 -0700259 static int FlagsOf(Code opcode) {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800260 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700261 }
262
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700263 // Returns true if this instruction is a branch.
264 bool IsBranch() const {
265 return (kInstructionFlags[Opcode()] & kBranch) != 0;
266 }
267
TDYa127526643e2012-05-26 01:01:48 -0700268 // Returns true if this instruction is a unconditional branch.
269 bool IsUnconditional() const {
270 return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
271 }
272
jeffhaoba5ebb92011-08-25 17:24:37 -0700273 // Returns true if this instruction is a switch.
274 bool IsSwitch() const {
275 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
276 }
277
278 // Returns true if this instruction can throw.
279 bool IsThrow() const {
280 return (kInstructionFlags[Opcode()] & kThrow) != 0;
281 }
282
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700283 // Determine if the instruction is any of 'return' instructions.
284 bool IsReturn() const {
285 return (kInstructionFlags[Opcode()] & kReturn) != 0;
286 }
287
288 // Determine if this instruction ends execution of its basic block.
289 bool IsBasicBlockEnd() const {
290 return IsBranch() || IsReturn() || Opcode() == THROW;
291 }
292
293 // Determine if this instruction is an invoke.
294 bool IsInvoke() const {
295 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
296 }
297
jeffhaoba5ebb92011-08-25 17:24:37 -0700298 int GetVerifyTypeArgumentA() const {
299 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
300 }
301
302 int GetVerifyTypeArgumentB() const {
303 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
304 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
305 }
306
307 int GetVerifyTypeArgumentC() const {
308 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
jeffhao3bb32462012-02-01 16:12:27 -0800309 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700310 }
311
312 int GetVerifyExtraFlags() const {
313 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
314 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
315 }
316
Ian Rogers2fa6b2e2012-10-17 00:10:17 -0700317 // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
318 uint32_t GetDexPc(const uint16_t* insns) const {
319 return (reinterpret_cast<const uint16_t*>(this) - insns);
320 }
321
Ian Rogersd81871c2011-10-03 13:57:23 -0700322 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700323 std::string DumpString(const DexFile*) const;
324
325 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
326 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700327
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700328 private:
Ian Rogersa75a0132012-09-28 11:41:42 -0700329 size_t SizeInCodeUnitsComplexOpcode() const;
330
Sebastien Hertz807a2562013-04-15 09:33:39 +0200331 uint16_t Fetch16(size_t offset) const {
332 const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
333 return insns[offset];
334 }
335
336 uint32_t Fetch32(size_t offset) const {
337 return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
338 }
339
340 uint4_t InstA() const {
341 return static_cast<uint4_t>((Fetch16(0) >> 8) & 0x0f);
342 }
343
344 uint4_t InstB() const {
345 return static_cast<uint4_t>(Fetch16(0) >> 12);
346 }
347
348 uint8_t InstAA() const {
349 return static_cast<uint8_t>(Fetch16(0) >> 8);
350 }
351
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700352 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800353 static Format const kInstructionFormats[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700354 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700355 static int const kInstructionVerifyFlags[];
Ian Rogersa75a0132012-09-28 11:41:42 -0700356 static int const kInstructionSizeInCodeUnits[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700357 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
358};
Ian Rogersa75a0132012-09-28 11:41:42 -0700359std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
360std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
361std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
362std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
Elliott Hughesadb8c672012-03-06 16:49:32 -0800363
364/*
365 * Holds the contents of a decoded instruction.
366 */
367struct DecodedInstruction {
368 uint32_t vA;
369 uint32_t vB;
370 uint64_t vB_wide; /* for k51l */
371 uint32_t vC;
372 uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
373 Instruction::Code opcode;
374
Ian Rogersa75a0132012-09-28 11:41:42 -0700375 explicit DecodedInstruction(const Instruction* inst) {
376 inst->Decode(vA, vB, vB_wide, vC, arg);
377 opcode = inst->Opcode();
378 }
Elliott Hughesadb8c672012-03-06 16:49:32 -0800379};
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700380
381} // namespace art
382
383#endif // ART_SRC_DEX_INSTRUCTION_H_