blob: 91aa042cf9af47992ed4339a1c7f9cf33d28c9a0 [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
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070020#include "globals.h"
21#include "logging.h"
22#include "macros.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070023
24namespace art {
25
Ian Rogersd81871c2011-10-03 13:57:23 -070026class DexFile;
27
Elliott Hughesadb8c672012-03-06 16:49:32 -080028enum {
29 kNumPackedOpcodes = 0x100
30};
31
Carl Shapiro12eb78e2011-06-24 14:51:06 -070032class Instruction {
33 public:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070034 // NOP-encoded switch-statement signatures.
35 enum {
36 kPackedSwitchSignature = 0x0100,
37 kSparseSwitchSignature = 0x0200,
Elliott Hughesadb8c672012-03-06 16:49:32 -080038 kArrayDataSignature = 0x0300,
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070039 };
40
Logan Chien19c350a2012-05-01 19:21:32 +080041 struct PACKED PackedSwitchPayload {
42 const uint16_t ident;
43 const uint16_t case_count;
44 const int32_t first_key;
45 const int32_t targets[];
46 private:
47 DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
48 };
49
50 struct PACKED SparseSwitchPayload {
51 const uint16_t ident;
52 const uint16_t case_count;
53 const int32_t keys_and_targets[];
54
55 public:
56 const int32_t* GetKeys() const {
57 return keys_and_targets;
58 }
59
60 const int32_t* GetTargets() const {
61 return keys_and_targets + case_count;
62 }
63
64 private:
65 DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
66 };
67
68 struct PACKED ArrayDataPayload {
69 const uint16_t ident;
70 const uint16_t element_width;
71 const uint32_t element_count;
72 const uint8_t data[];
73 private:
74 DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
75 };
76
Carl Shapiro12eb78e2011-06-24 14:51:06 -070077 enum Code {
jeffhaoba5ebb92011-08-25 17:24:37 -070078#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070079#include "dex_instruction_list.h"
Carl Shapiro12eb78e2011-06-24 14:51:06 -070080 DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
Carl Shapirod84f49c2011-06-29 00:27:46 -070081#undef DEX_INSTRUCTION_LIST
Carl Shapiro12eb78e2011-06-24 14:51:06 -070082#undef INSTRUCTION_ENUM
Carl Shapirod84f49c2011-06-29 00:27:46 -070083 };
Carl Shapiro12eb78e2011-06-24 14:51:06 -070084
Elliott Hughesadb8c672012-03-06 16:49:32 -080085 enum Format {
Carl Shapiroe4c1ce42011-07-09 02:31:57 -070086 k10x, // op
87 k12x, // op vA, vB
88 k11n, // op vA, #+B
89 k11x, // op vAA
90 k10t, // op +AA
91 k20t, // op +AAAA
92 k22x, // op vAA, vBBBB
93 k21t, // op vAA, +BBBB
94 k21s, // op vAA, #+BBBB
95 k21h, // op vAA, #+BBBB00000[00000000]
96 k21c, // op vAA, thing@BBBB
97 k23x, // op vAA, vBB, vCC
98 k22b, // op vAA, vBB, #+CC
99 k22t, // op vA, vB, +CCCC
100 k22s, // op vA, vB, #+CCCC
101 k22c, // op vA, vB, thing@CCCC
102 k32x, // op vAAAA, vBBBB
103 k30t, // op +AAAAAAAA
104 k31t, // op vAA, +BBBBBBBB
105 k31i, // op vAA, #+BBBBBBBB
106 k31c, // op vAA, thing@BBBBBBBB
107 k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
108 k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
109 k51l, // op vAA, #+BBBBBBBBBBBBBBBB
110 };
111
112 enum Flags {
113 kBranch = 0x01, // conditional or unconditional branch
114 kContinue = 0x02, // flow can continue to next statement
115 kSwitch = 0x04, // switch statement
116 kThrow = 0x08, // could cause an exception to be thrown
117 kReturn = 0x10, // returns, no additional statements
118 kInvoke = 0x20, // a flavor of invoke
TDYa127526643e2012-05-26 01:01:48 -0700119 kUnconditional = 0x40, // unconditional branch
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700120 };
121
jeffhaoba5ebb92011-08-25 17:24:37 -0700122 enum VerifyFlag {
123 kVerifyNone = 0x00000,
124 kVerifyRegA = 0x00001,
125 kVerifyRegAWide = 0x00002,
126 kVerifyRegB = 0x00004,
127 kVerifyRegBField = 0x00008,
128 kVerifyRegBMethod = 0x00010,
129 kVerifyRegBNewInstance = 0x00020,
130 kVerifyRegBString = 0x00040,
131 kVerifyRegBType = 0x00080,
132 kVerifyRegBWide = 0x00100,
133 kVerifyRegC = 0x00200,
134 kVerifyRegCField = 0x00400,
135 kVerifyRegCNewArray = 0x00800,
136 kVerifyRegCType = 0x01000,
137 kVerifyRegCWide = 0x02000,
138 kVerifyArrayData = 0x04000,
139 kVerifyBranchTarget = 0x08000,
140 kVerifySwitchTargets = 0x10000,
141 kVerifyVarArg = 0x20000,
142 kVerifyVarArgRange = 0x40000,
143 kVerifyError = 0x80000,
144 };
145
146 // Decodes this instruction, populating its arguments.
147 void Decode(uint32_t &vA, uint32_t &vB, uint64_t &vB_wide, uint32_t &vC, uint32_t arg[]) const;
148
Elliott Hughesadb8c672012-03-06 16:49:32 -0800149 // Returns the size (in 2 byte code units) of this instruction.
Ian Rogersd81871c2011-10-03 13:57:23 -0700150 size_t SizeInCodeUnits() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700151
152 // Returns a pointer to the next instruction in the stream.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700153 const Instruction* Next() const;
154
Elliott Hughesadb8c672012-03-06 16:49:32 -0800155 // Returns the name of this instruction's opcode.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700156 const char* Name() const {
Elliott Hughesadb8c672012-03-06 16:49:32 -0800157 return Instruction::Name(Opcode());
158 }
159
160 // Returns the name of the given opcode.
161 static const char* Name(Code opcode) {
162 return kInstructionNames[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700163 }
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700164
165 // Returns the opcode field of the instruction.
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700166 Code Opcode() const;
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700167
168 // Reads an instruction out of the stream at the specified address.
Ian Rogersd81871c2011-10-03 13:57:23 -0700169 static const Instruction* At(const uint16_t* code) {
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700170 CHECK(code != NULL);
jeffhaoba5ebb92011-08-25 17:24:37 -0700171 return reinterpret_cast<const Instruction*>(code);
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700172 }
173
Elliott Hughesadb8c672012-03-06 16:49:32 -0800174 // Returns the format of the given opcode.
175 static Format FormatOf(Code opcode) {
176 return kInstructionFormats[opcode];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700177 }
178
Elliott Hughesadb8c672012-03-06 16:49:32 -0800179 // Returns the flags for the given opcode.
180 static int Flags(Code opcode) {
181 return kInstructionFlags[opcode];
jeffhaobdb76512011-09-07 11:43:16 -0700182 }
183
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700184 // Returns true if this instruction is a branch.
185 bool IsBranch() const {
186 return (kInstructionFlags[Opcode()] & kBranch) != 0;
187 }
188
TDYa127526643e2012-05-26 01:01:48 -0700189 // Returns true if this instruction is a unconditional branch.
190 bool IsUnconditional() const {
191 return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
192 }
193
jeffhaoba5ebb92011-08-25 17:24:37 -0700194 // Returns true if this instruction is a switch.
195 bool IsSwitch() const {
196 return (kInstructionFlags[Opcode()] & kSwitch) != 0;
197 }
198
199 // Returns true if this instruction can throw.
200 bool IsThrow() const {
201 return (kInstructionFlags[Opcode()] & kThrow) != 0;
202 }
203
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700204 // Determine if the instruction is any of 'return' instructions.
205 bool IsReturn() const {
206 return (kInstructionFlags[Opcode()] & kReturn) != 0;
207 }
208
209 // Determine if this instruction ends execution of its basic block.
210 bool IsBasicBlockEnd() const {
211 return IsBranch() || IsReturn() || Opcode() == THROW;
212 }
213
214 // Determine if this instruction is an invoke.
215 bool IsInvoke() const {
216 return (kInstructionFlags[Opcode()] & kInvoke) != 0;
217 }
218
jeffhaoba5ebb92011-08-25 17:24:37 -0700219 int GetVerifyTypeArgumentA() const {
220 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
221 }
222
223 int GetVerifyTypeArgumentB() const {
224 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod |
225 kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide));
226 }
227
228 int GetVerifyTypeArgumentC() const {
229 return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
jeffhao3bb32462012-02-01 16:12:27 -0800230 kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
jeffhaoba5ebb92011-08-25 17:24:37 -0700231 }
232
233 int GetVerifyExtraFlags() const {
234 return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
235 kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgRange | kVerifyError));
236 }
237
Ian Rogersd81871c2011-10-03 13:57:23 -0700238 // Dump decoded version of instruction
Ian Rogers2c8a8572011-10-24 17:11:36 -0700239 std::string DumpString(const DexFile*) const;
240
241 // Dump code_units worth of this instruction, padding to code_units for shorter instructions
242 std::string DumpHex(size_t code_units) const;
Ian Rogersd81871c2011-10-03 13:57:23 -0700243
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700244 private:
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700245 static const char* const kInstructionNames[];
Elliott Hughesadb8c672012-03-06 16:49:32 -0800246 static Format const kInstructionFormats[];
Carl Shapiroe4c1ce42011-07-09 02:31:57 -0700247 static int const kInstructionFlags[];
jeffhaoba5ebb92011-08-25 17:24:37 -0700248 static int const kInstructionVerifyFlags[];
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700249 DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
250};
Elliott Hughesadb8c672012-03-06 16:49:32 -0800251
252/*
253 * Holds the contents of a decoded instruction.
254 */
255struct DecodedInstruction {
256 uint32_t vA;
257 uint32_t vB;
258 uint64_t vB_wide; /* for k51l */
259 uint32_t vC;
260 uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */
261 Instruction::Code opcode;
262
263 explicit DecodedInstruction(const Instruction* inst);
264};
Carl Shapiro12eb78e2011-06-24 14:51:06 -0700265
266} // namespace art
267
268#endif // ART_SRC_DEX_INSTRUCTION_H_